mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 19:42:36 +02:00
GP-3235 improved auto-assignment of VOID storage to void return type for
function
This commit is contained in:
parent
8dd584c9bc
commit
19c1e8ae5b
17 changed files with 119 additions and 86 deletions
|
@ -47,6 +47,7 @@ import ghidra.app.util.cparser.C.CParserUtils;
|
||||||
import ghidra.app.util.viewer.field.ListingColors.FunctionColors;
|
import ghidra.app.util.viewer.field.ListingColors.FunctionColors;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
|
import ghidra.program.model.data.VoidDataType;
|
||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.Function;
|
||||||
import ghidra.program.model.listing.VariableStorage;
|
import ghidra.program.model.listing.VariableStorage;
|
||||||
import ghidra.program.model.symbol.ExternalLocation;
|
import ghidra.program.model.symbol.ExternalLocation;
|
||||||
|
@ -747,8 +748,15 @@ public class FunctionEditorDialog extends DialogComponentProvider implements Mod
|
||||||
setStatusText("Return name may not be modified");
|
setStatusText("Return name may not be modified");
|
||||||
}
|
}
|
||||||
else if ("Storage".equals(getColumnName(column))) {
|
else if ("Storage".equals(getColumnName(column))) {
|
||||||
setStatusText(
|
boolean blockVoidStorageEdit = (rowData.getIndex() == null) &&
|
||||||
"Enable 'Use Custom Storage' to allow editing of Parameter and Return Storage");
|
VoidDataType.isVoidDataType(rowData.getFormalDataType());
|
||||||
|
if (!blockVoidStorageEdit) {
|
||||||
|
setStatusText(
|
||||||
|
"Enable 'Use Custom Storage' to allow editing of Parameter and Return Storage");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setStatusText("Void return storage may not be modified");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,6 +96,13 @@ public class FunctionEditorModel {
|
||||||
|
|
||||||
returnInfo = new ParamInfo(this, function.getReturn());
|
returnInfo = new ParamInfo(this, function.getReturn());
|
||||||
|
|
||||||
|
// check for void storage correction
|
||||||
|
if (VoidDataType.isVoidDataType(returnInfo.getDataType()) &&
|
||||||
|
returnInfo.getStorage() != VariableStorage.VOID_STORAGE) {
|
||||||
|
returnInfo.setStorage(VariableStorage.VOID_STORAGE);
|
||||||
|
modelChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
autoParamCount = 0;
|
autoParamCount = 0;
|
||||||
Parameter[] params = function.getParameters();
|
Parameter[] params = function.getParameters();
|
||||||
for (Parameter parameter : params) {
|
for (Parameter parameter : params) {
|
||||||
|
@ -265,7 +272,7 @@ public class FunctionEditorModel {
|
||||||
}
|
}
|
||||||
else if (!allowCustomStorage &&
|
else if (!allowCustomStorage &&
|
||||||
Function.UNKNOWN_CALLING_CONVENTION_STRING.equals(callingConventionName)) {
|
Function.UNKNOWN_CALLING_CONVENTION_STRING.equals(callingConventionName)) {
|
||||||
if (!(returnType instanceof VoidDataType && parameters.isEmpty())) {
|
if (!(VoidDataType.isVoidDataType(returnType) && parameters.isEmpty())) {
|
||||||
statusText =
|
statusText =
|
||||||
"Warning: No calling convention specified. Ghidra may automatically assign one later.";
|
"Warning: No calling convention specified. Ghidra may automatically assign one later.";
|
||||||
}
|
}
|
||||||
|
@ -338,17 +345,9 @@ public class FunctionEditorModel {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataType getBaseDataType(DataType dataType) {
|
|
||||||
if (dataType instanceof TypeDef) {
|
|
||||||
return ((TypeDef) dataType).getBaseDataType();
|
|
||||||
}
|
|
||||||
return dataType;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean hasValidReturnType() {
|
private boolean hasValidReturnType() {
|
||||||
DataType returnType = returnInfo.getDataType();
|
DataType returnType = returnInfo.getDataType();
|
||||||
DataType baseType = getBaseDataType(returnType);
|
if (VoidDataType.isVoidDataType(returnType)) {
|
||||||
if (baseType instanceof VoidDataType) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (returnType.getLength() <= 0) {
|
if (returnType.getLength() <= 0) {
|
||||||
|
@ -377,7 +376,7 @@ public class FunctionEditorModel {
|
||||||
|
|
||||||
private boolean isValidParamType(ParamInfo param) {
|
private boolean isValidParamType(ParamInfo param) {
|
||||||
DataType dataType = param.getDataType();
|
DataType dataType = param.getDataType();
|
||||||
if (dataType.isEquivalent(VoidDataType.dataType)) {
|
if (VoidDataType.isVoidDataType(dataType)) {
|
||||||
statusText = "\"void\" is not allowed as a parameter datatype.";
|
statusText = "\"void\" is not allowed as a parameter datatype.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -800,7 +799,7 @@ public class FunctionEditorModel {
|
||||||
|
|
||||||
param.setFormalDataType(formalDataType.clone(program.getDataTypeManager()));
|
param.setFormalDataType(formalDataType.clone(program.getDataTypeManager()));
|
||||||
if (allowCustomStorage) {
|
if (allowCustomStorage) {
|
||||||
if (isReturn && (formalDataType instanceof VoidDataType)) {
|
if (isReturn && VoidDataType.isVoidDataType(formalDataType)) {
|
||||||
param.setStorage(VariableStorage.VOID_STORAGE);
|
param.setStorage(VariableStorage.VOID_STORAGE);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1099,10 +1098,8 @@ public class FunctionEditorModel {
|
||||||
|
|
||||||
setCallingConventionName(functionDefinition.getCallingConventionName());
|
setCallingConventionName(functionDefinition.getCallingConventionName());
|
||||||
|
|
||||||
if (!isSameSize(returnInfo.getFormalDataType(), functionDefinition.getReturnType())) {
|
DataType returnDt = functionDefinition.getReturnType();
|
||||||
returnInfo.setStorage(VariableStorage.UNASSIGNED_STORAGE);
|
returnInfo.setFormalDataType(returnDt);
|
||||||
}
|
|
||||||
returnInfo.setFormalDataType(functionDefinition.getReturnType());
|
|
||||||
|
|
||||||
List<ParamInfo> oldParams = parameters;
|
List<ParamInfo> oldParams = parameters;
|
||||||
parameters = new ArrayList<>();
|
parameters = new ArrayList<>();
|
||||||
|
@ -1117,6 +1114,13 @@ public class FunctionEditorModel {
|
||||||
fixupOrdinals();
|
fixupOrdinals();
|
||||||
|
|
||||||
if (allowCustomStorage) {
|
if (allowCustomStorage) {
|
||||||
|
if (VoidDataType.isVoidDataType(returnDt)) {
|
||||||
|
returnInfo.setStorage(VariableStorage.VOID_STORAGE);
|
||||||
|
}
|
||||||
|
else if (!isSameSize(returnInfo.getFormalDataType(),
|
||||||
|
functionDefinition.getReturnType())) {
|
||||||
|
returnInfo.setStorage(VariableStorage.UNASSIGNED_STORAGE);
|
||||||
|
}
|
||||||
reconcileCustomStorage(oldParams, parameters);
|
reconcileCustomStorage(oldParams, parameters);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -19,6 +19,10 @@ import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.listing.VariableStorage;
|
import ghidra.program.model.listing.VariableStorage;
|
||||||
|
|
||||||
interface FunctionVariableData {
|
interface FunctionVariableData {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return parameter ordinal or null for return variable.}
|
||||||
|
*/
|
||||||
public Integer getIndex();
|
public Integer getIndex();
|
||||||
|
|
||||||
public void setStorage(VariableStorage storage);
|
public void setStorage(VariableStorage storage);
|
||||||
|
|
|
@ -20,6 +20,7 @@ import java.util.List;
|
||||||
|
|
||||||
import docking.widgets.table.AbstractGTableModel;
|
import docking.widgets.table.AbstractGTableModel;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
|
import ghidra.program.model.data.VoidDataType;
|
||||||
import ghidra.program.model.listing.VariableStorage;
|
import ghidra.program.model.listing.VariableStorage;
|
||||||
|
|
||||||
class ParameterTableModel extends AbstractGTableModel<FunctionVariableData> {
|
class ParameterTableModel extends AbstractGTableModel<FunctionVariableData> {
|
||||||
|
@ -223,7 +224,15 @@ class ParameterTableModel extends AbstractGTableModel<FunctionVariableData> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCellEditable(int rowIndex) {
|
public boolean isCellEditable(int rowIndex) {
|
||||||
return canCustomizeStorage;
|
FunctionVariableData rowData = getRowObject(rowIndex);
|
||||||
|
if (rowData == null || !canCustomizeStorage) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (rowData.getIndex() == null) {
|
||||||
|
// return parameter - don't permit storage edit for void type
|
||||||
|
return !VoidDataType.isVoidDataType(rowData.getFormalDataType());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -208,7 +208,7 @@ public class DwarfDecoderFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataType getDataType(Program program) {
|
public DataType getDataType(Program program) {
|
||||||
return new VoidDataType();
|
return VoidDataType.dataType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,7 +370,7 @@ public class DwarfDecoderFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataType getDataType(Program program) {
|
public DataType getDataType(Program program) {
|
||||||
return new VoidDataType();
|
return VoidDataType.dataType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -327,11 +327,8 @@ public class UndefinedFunction implements Function {
|
||||||
public Parameter getReturn() {
|
public Parameter getReturn() {
|
||||||
try {
|
try {
|
||||||
DataType dt = getReturnType();
|
DataType dt = getReturnType();
|
||||||
if (dt instanceof TypeDef) {
|
|
||||||
dt = ((TypeDef) dt).getBaseDataType();
|
|
||||||
}
|
|
||||||
return new ReturnParameterImpl(dt,
|
return new ReturnParameterImpl(dt,
|
||||||
(dt instanceof VoidDataType) ? VariableStorage.VOID_STORAGE
|
VoidDataType.isVoidDataType(dt) ? VariableStorage.VOID_STORAGE
|
||||||
: VariableStorage.UNASSIGNED_STORAGE,
|
: VariableStorage.UNASSIGNED_STORAGE,
|
||||||
getProgram());
|
getProgram());
|
||||||
}
|
}
|
||||||
|
|
|
@ -2168,7 +2168,7 @@ public class ResultsState {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
returnType = func.getReturnType();
|
returnType = func.getReturnType();
|
||||||
if (VoidDataType.dataType.isEquivalent(returnType)) {
|
if (VoidDataType.isVoidDataType(returnType)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3288,8 +3288,7 @@ public class RecoveredClassHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (returnType.equals("void")) {
|
if (returnType.equals("void")) {
|
||||||
DataType voidDataType = new VoidDataType();
|
constructorFunction.setReturnType(VoidDataType.dataType, SourceType.ANALYSIS);
|
||||||
constructorFunction.setReturnType(voidDataType, SourceType.ANALYSIS);
|
|
||||||
}
|
}
|
||||||
else if (returnType.contains("*")) {
|
else if (returnType.contains("*")) {
|
||||||
DataType classPointerDataType = dataTypeManager.getPointer(classStruct);
|
DataType classPointerDataType = dataTypeManager.getPointer(classStruct);
|
||||||
|
@ -3353,7 +3352,7 @@ public class RecoveredClassHelper {
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
destructorFunction.setReturnType(new VoidDataType(), SourceType.ANALYSIS);
|
destructorFunction.setReturnType(VoidDataType.dataType, SourceType.ANALYSIS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3400,7 +3399,7 @@ public class RecoveredClassHelper {
|
||||||
true, true);
|
true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
vbaseDestructorFunction.setReturnType(new VoidDataType(), SourceType.ANALYSIS);
|
vbaseDestructorFunction.setReturnType(VoidDataType.dataType, SourceType.ANALYSIS);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6220,7 +6219,7 @@ public class RecoveredClassHelper {
|
||||||
if (!atexitCalledFunctions.contains(calledFunction)) {
|
if (!atexitCalledFunctions.contains(calledFunction)) {
|
||||||
atexitCalledFunctions.add(calledFunction);
|
atexitCalledFunctions.add(calledFunction);
|
||||||
}
|
}
|
||||||
calledFunction.setReturnType(new VoidDataType(), SourceType.ANALYSIS);
|
calledFunction.setReturnType(VoidDataType.dataType, SourceType.ANALYSIS);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!atexitCalledFunctions.contains(calledFunction)) {
|
if (!atexitCalledFunctions.contains(calledFunction)) {
|
||||||
|
|
|
@ -79,8 +79,7 @@ public class PdbPrimitiveTypeApplicator {
|
||||||
|
|
||||||
DataType getVoidType() {
|
DataType getVoidType() {
|
||||||
if (voidGhidraPrimitive == null) {
|
if (voidGhidraPrimitive == null) {
|
||||||
DataType dataType = new VoidDataType(getDataTypeManager());
|
voidGhidraPrimitive = resolve(VoidDataType.dataType);
|
||||||
voidGhidraPrimitive = resolve(dataType);
|
|
||||||
}
|
}
|
||||||
return voidGhidraPrimitive;
|
return voidGhidraPrimitive;
|
||||||
}
|
}
|
||||||
|
|
|
@ -392,7 +392,10 @@ public class FunctionDB extends DatabaseObject implements Function {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
type = type.clone(program.getDataTypeManager());
|
type = type.clone(program.getDataTypeManager());
|
||||||
if (storage.isValid() && (storage.size() != type.getLength())) {
|
if (VoidDataType.isVoidDataType(type)) {
|
||||||
|
storage = VariableStorage.VOID_STORAGE;
|
||||||
|
}
|
||||||
|
else if (storage.isValid() && (storage.size() != type.getLength())) {
|
||||||
try {
|
try {
|
||||||
storage = VariableUtilities.resizeStorage(storage, type, true, this);
|
storage = VariableUtilities.resizeStorage(storage, type, true, this);
|
||||||
}
|
}
|
||||||
|
@ -811,13 +814,9 @@ public class FunctionDB extends DatabaseObject implements Function {
|
||||||
}
|
}
|
||||||
|
|
||||||
dataTypes[0] = returnParam.getFormalDataType();
|
dataTypes[0] = returnParam.getFormalDataType();
|
||||||
DataType baseType = dataTypes[0];
|
returnParam.setDynamicStorage(
|
||||||
if (baseType instanceof TypeDef) {
|
VoidDataType.isVoidDataType(dataTypes[0]) ? VariableStorage.VOID_STORAGE
|
||||||
baseType = ((TypeDef) baseType).getBaseDataType();
|
: VariableStorage.UNASSIGNED_STORAGE);
|
||||||
}
|
|
||||||
returnParam
|
|
||||||
.setDynamicStorage((baseType instanceof VoidDataType) ? VariableStorage.VOID_STORAGE
|
|
||||||
: VariableStorage.UNASSIGNED_STORAGE);
|
|
||||||
|
|
||||||
PrototypeModel callingConvention = getCallingConvention();
|
PrototypeModel callingConvention = getCallingConvention();
|
||||||
if (callingConvention == null) {
|
if (callingConvention == null) {
|
||||||
|
@ -913,12 +912,8 @@ public class FunctionDB extends DatabaseObject implements Function {
|
||||||
ReturnParameterDB rtnParam = getReturn();
|
ReturnParameterDB rtnParam = getReturn();
|
||||||
if (rtnParam.getVariableStorage().isBadStorage()) {
|
if (rtnParam.getVariableStorage().isBadStorage()) {
|
||||||
DataType dt = rtnParam.getDataType();
|
DataType dt = rtnParam.getDataType();
|
||||||
DataType baseType = dt;
|
|
||||||
if (baseType instanceof TypeDef) {
|
|
||||||
baseType = ((TypeDef) baseType).getBaseDataType();
|
|
||||||
}
|
|
||||||
VariableStorage storage =
|
VariableStorage storage =
|
||||||
(baseType instanceof VoidDataType) ? VariableStorage.VOID_STORAGE
|
VoidDataType.isVoidDataType(dt) ? VariableStorage.VOID_STORAGE
|
||||||
: VariableStorage.UNASSIGNED_STORAGE;
|
: VariableStorage.UNASSIGNED_STORAGE;
|
||||||
rtnParam.setStorageAndDataType(storage, dt);
|
rtnParam.setStorageAndDataType(storage, dt);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,10 +22,6 @@ import ghidra.program.model.listing.*;
|
||||||
|
|
||||||
class ParameterDB extends VariableDB implements Parameter {
|
class ParameterDB extends VariableDB implements Parameter {
|
||||||
|
|
||||||
/**
|
|
||||||
* @param function
|
|
||||||
* @param s
|
|
||||||
*/
|
|
||||||
ParameterDB(FunctionDB function, SymbolDB s) {
|
ParameterDB(FunctionDB function, SymbolDB s) {
|
||||||
super(function, s);
|
super(function, s);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,16 +28,17 @@ public class ReturnParameterDB extends ParameterDB {
|
||||||
|
|
||||||
private DataType dataType;
|
private DataType dataType;
|
||||||
|
|
||||||
/**
|
|
||||||
* @param function
|
|
||||||
* @param s
|
|
||||||
*/
|
|
||||||
ReturnParameterDB(FunctionDB function, DataType dt, VariableStorage storage) {
|
ReturnParameterDB(FunctionDB function, DataType dt, VariableStorage storage) {
|
||||||
super(function, null);
|
super(function, null);
|
||||||
this.dataType = dt;
|
this.dataType = dt;
|
||||||
this.storage = storage;
|
this.storage = storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isVoidAllowed() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return RETURN_NAME;
|
return RETURN_NAME;
|
||||||
|
@ -123,15 +124,10 @@ public class ReturnParameterDB extends ParameterDB {
|
||||||
VariableStorage newStorage = VariableStorage.UNASSIGNED_STORAGE;
|
VariableStorage newStorage = VariableStorage.UNASSIGNED_STORAGE;
|
||||||
boolean hasCustomVariableStorage = function.hasCustomVariableStorage();
|
boolean hasCustomVariableStorage = function.hasCustomVariableStorage();
|
||||||
if (hasCustomVariableStorage) {
|
if (hasCustomVariableStorage) {
|
||||||
DataType baseType = type;
|
|
||||||
if (baseType instanceof TypeDef) {
|
|
||||||
baseType = ((TypeDef) baseType).getBaseDataType();
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
newStorage =
|
newStorage = VoidDataType.isVoidDataType(type) ? VariableStorage.VOID_STORAGE
|
||||||
(baseType instanceof VoidDataType) ? VariableStorage.VOID_STORAGE
|
: VariableUtilities.resizeStorage(getVariableStorage(), type,
|
||||||
: VariableUtilities.resizeStorage(getVariableStorage(), type,
|
alignStack, function);
|
||||||
alignStack, function);
|
|
||||||
VariableUtilities.checkStorage(newStorage, type, force);
|
VariableUtilities.checkStorage(newStorage, type, force);
|
||||||
}
|
}
|
||||||
catch (InvalidInputException e) {
|
catch (InvalidInputException e) {
|
||||||
|
|
|
@ -23,8 +23,8 @@ import ghidra.program.database.data.DataTypeUtilities;
|
||||||
import ghidra.program.database.symbol.SymbolDB;
|
import ghidra.program.database.symbol.SymbolDB;
|
||||||
import ghidra.program.database.symbol.VariableSymbolDB;
|
import ghidra.program.database.symbol.VariableSymbolDB;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.AbstractFloatDataType;
|
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
|
import ghidra.program.model.data.VoidDataType;
|
||||||
import ghidra.program.model.lang.Register;
|
import ghidra.program.model.lang.Register;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.pcode.Varnode;
|
import ghidra.program.model.pcode.Varnode;
|
||||||
|
@ -53,12 +53,21 @@ public abstract class VariableDB implements Variable {
|
||||||
this.functionMgr = function.getFunctionManager();
|
this.functionMgr = function.getFunctionManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean isVoidAllowed() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isValid() {
|
public final boolean isValid() {
|
||||||
VariableStorage variableStorage = getVariableStorage();
|
VariableStorage variableStorage = getVariableStorage();
|
||||||
DataType dt = getDataType();
|
DataType dt = getDataType();
|
||||||
return variableStorage.isValid() &&
|
if (VoidDataType.isVoidDataType(dt)) {
|
||||||
((dt instanceof AbstractFloatDataType) || variableStorage.size() == dt.getLength());
|
return isVoidAllowed() && variableStorage.isVoidStorage();
|
||||||
|
}
|
||||||
|
if (dt.getLength() <= 0 || !variableStorage.isValid()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return variableStorage.size() >= dt.getLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -93,4 +93,20 @@ public class VoidDataType extends BuiltIn {
|
||||||
return null; // standard C name and type
|
return null; // standard C name and type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the specified {@link DataType} is a {@link VoidDataType} after
|
||||||
|
* stripping away any {@link TypeDef}.
|
||||||
|
* @param dt datatype to be tested
|
||||||
|
* @return true if dt is a void type
|
||||||
|
*/
|
||||||
|
public static boolean isVoidDataType(DataType dt) {
|
||||||
|
if (dt == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (dt instanceof TypeDef t) {
|
||||||
|
dt = t.getBaseDataType();
|
||||||
|
}
|
||||||
|
return dt instanceof VoidDataType;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,11 +80,7 @@ public class ParamListStandard implements ParamList {
|
||||||
if (tp == null) {
|
if (tp == null) {
|
||||||
tp = DataType.DEFAULT;
|
tp = DataType.DEFAULT;
|
||||||
}
|
}
|
||||||
DataType baseType = tp;
|
if (VoidDataType.isVoidDataType(tp)) {
|
||||||
if (baseType instanceof TypeDef) {
|
|
||||||
baseType = ((TypeDef) baseType).getBaseDataType();
|
|
||||||
}
|
|
||||||
if (baseType instanceof VoidDataType) {
|
|
||||||
return VariableStorage.VOID_STORAGE;
|
return VariableStorage.VOID_STORAGE;
|
||||||
}
|
}
|
||||||
int sz = tp.getLength();
|
int sz = tp.getLength();
|
||||||
|
|
|
@ -264,9 +264,13 @@ abstract class VariableImpl implements Variable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final boolean isValid() {
|
public final boolean isValid() {
|
||||||
DataType dt = getDataType();
|
if (VoidDataType.isVoidDataType(dataType)) {
|
||||||
return variableStorage.isValid() &&
|
return isVoidAllowed() && variableStorage.isVoidStorage();
|
||||||
((dt instanceof AbstractFloatDataType) || variableStorage.size() == dt.getLength());
|
}
|
||||||
|
if (dataType.getLength() <= 0 || !variableStorage.isValid()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return variableStorage.size() >= dataType.getLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -302,11 +306,7 @@ abstract class VariableImpl implements Variable {
|
||||||
public void setDataType(DataType type, SourceType source) throws InvalidInputException {
|
public void setDataType(DataType type, SourceType source) throws InvalidInputException {
|
||||||
type =
|
type =
|
||||||
VariableUtilities.checkDataType(type, isVoidAllowed(), dataType.getLength(), program);
|
VariableUtilities.checkDataType(type, isVoidAllowed(), dataType.getLength(), program);
|
||||||
DataType baseType = type;
|
variableStorage = VoidDataType.isVoidDataType(type) ? VariableStorage.VOID_STORAGE
|
||||||
if (baseType instanceof TypeDef) {
|
|
||||||
baseType = ((TypeDef) baseType).getBaseDataType();
|
|
||||||
}
|
|
||||||
variableStorage = (baseType instanceof VoidDataType) ? VariableStorage.VOID_STORAGE
|
|
||||||
: resizeStorage(variableStorage, type);
|
: resizeStorage(variableStorage, type);
|
||||||
dataType = type;
|
dataType = type;
|
||||||
}
|
}
|
||||||
|
|
|
@ -372,6 +372,17 @@ public class VariableUtilities {
|
||||||
*/
|
*/
|
||||||
public static VariableStorage resizeStorage(VariableStorage curStorage, DataType dataType,
|
public static VariableStorage resizeStorage(VariableStorage curStorage, DataType dataType,
|
||||||
boolean alignStack, Function function) throws InvalidInputException {
|
boolean alignStack, Function function) throws InvalidInputException {
|
||||||
|
|
||||||
|
if (dataType instanceof TypeDef td) {
|
||||||
|
dataType = td.getBaseDataType();
|
||||||
|
}
|
||||||
|
if (dataType instanceof VoidDataType) {
|
||||||
|
return VariableStorage.VOID_STORAGE;
|
||||||
|
}
|
||||||
|
if (dataType instanceof AbstractFloatDataType) {
|
||||||
|
return curStorage; // do not constrain or attempt resize of float storage
|
||||||
|
}
|
||||||
|
|
||||||
if (!curStorage.isValid()) {
|
if (!curStorage.isValid()) {
|
||||||
return curStorage;
|
return curStorage;
|
||||||
}
|
}
|
||||||
|
@ -380,17 +391,11 @@ public class VariableUtilities {
|
||||||
if (curSize == newSize) {
|
if (curSize == newSize) {
|
||||||
return curStorage;
|
return curStorage;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (curSize == 0 || curStorage.isUniqueStorage() || curStorage.isHashStorage()) {
|
if (curSize == 0 || curStorage.isUniqueStorage() || curStorage.isHashStorage()) {
|
||||||
throw new InvalidInputException("Storage can't be resized: " + curStorage.toString());
|
throw new InvalidInputException("Storage can't be resized: " + curStorage.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dataType instanceof TypeDef) {
|
|
||||||
dataType = ((TypeDef) dataType).getBaseDataType();
|
|
||||||
}
|
|
||||||
if (dataType instanceof AbstractFloatDataType) {
|
|
||||||
return curStorage; // do not constrain or attempt resize of float storage
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newSize > curSize) {
|
if (newSize > curSize) {
|
||||||
return expandStorage(curStorage, newSize, dataType, alignStack, function);
|
return expandStorage(curStorage, newSize, dataType, alignStack, function);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue