aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity
diff options
context:
space:
mode:
authormingchuan <mingc@skymizer.com>2018-05-23 12:31:20 +0800
committermingchuan <mingc@skymizer.com>2018-05-30 18:05:55 +0800
commitb7cafcbdf95c807f46fc07f4788d82981b7112b4 (patch)
tree5714a463da64eaf75a3ec56732165ec89e77d677 /libsolidity
parent9d5064d04d178474b95d67e87aaa32d0e5e03b0f (diff)
downloaddexon-solidity-b7cafcbdf95c807f46fc07f4788d82981b7112b4.tar.gz
dexon-solidity-b7cafcbdf95c807f46fc07f4788d82981b7112b4.tar.zst
dexon-solidity-b7cafcbdf95c807f46fc07f4788d82981b7112b4.zip
Allow using `calldata` keyword to specify data location
Diffstat (limited to 'libsolidity')
-rw-r--r--libsolidity/analysis/ReferencesResolver.cpp38
-rw-r--r--libsolidity/analysis/TypeChecker.cpp2
-rw-r--r--libsolidity/ast/AST.h2
-rw-r--r--libsolidity/ast/ASTJsonConverter.cpp2
-rw-r--r--libsolidity/ast/Types.cpp14
-rw-r--r--libsolidity/parsing/Parser.cpp21
-rw-r--r--libsolidity/parsing/Token.h5
7 files changed, 65 insertions, 19 deletions
diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp
index f91eaf6e..a051d7f9 100644
--- a/libsolidity/analysis/ReferencesResolver.cpp
+++ b/libsolidity/analysis/ReferencesResolver.cpp
@@ -327,7 +327,7 @@ void ReferencesResolver::endVisit(VariableDeclaration const& _variable)
else
{
// force location of external function parameters (not return) to calldata
- if (varLoc != Location::Default)
+ if (varLoc != Location::CallData && varLoc != Location::Default)
fatalTypeError(_variable.location(),
"Location has to be calldata for external functions "
"(remove the \"memory\" or \"storage\" keyword)."
@@ -344,15 +344,22 @@ void ReferencesResolver::endVisit(VariableDeclaration const& _variable)
*dynamic_cast<Declaration const&>(*_variable.scope()).scope()
);
// force locations of public or external function (return) parameters to memory
- if (varLoc == Location::Storage && !contract.isLibrary())
+ if (varLoc != Location::Memory && varLoc != Location::Default && !contract.isLibrary())
fatalTypeError(_variable.location(),
"Location has to be memory for publicly visible functions "
- "(remove the \"storage\" keyword)."
+ "(remove the \"storage\" or \"calldata\" keyword)."
);
if (varLoc == Location::Default || !contract.isLibrary())
typeLoc = DataLocation::Memory;
else
+ {
+ if (varLoc == Location::CallData)
+ fatalTypeError(_variable.location(),
+ "Location cannot be calldata for non-external functions "
+ "(remove the \"calldata\" keyword)."
+ );
typeLoc = varLoc == Location::Memory ? DataLocation::Memory : DataLocation::Storage;
+ }
}
else
{
@@ -361,7 +368,7 @@ void ReferencesResolver::endVisit(VariableDeclaration const& _variable)
if (varLoc != Location::Default && varLoc != Location::Memory)
fatalTypeError(
_variable.location(),
- "Storage location has to be \"memory\" (or unspecified) for constants."
+ "Data location has to be \"memory\" (or unspecified) for constants."
);
typeLoc = DataLocation::Memory;
}
@@ -377,7 +384,7 @@ void ReferencesResolver::endVisit(VariableDeclaration const& _variable)
if (_variable.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050))
typeError(
_variable.location(),
- "Storage location must be specified as either \"memory\" or \"storage\"."
+ "Data location must be specified as either \"memory\" or \"storage\"."
);
else
m_errorReporter.warning(
@@ -389,14 +396,31 @@ void ReferencesResolver::endVisit(VariableDeclaration const& _variable)
}
}
else
- typeLoc = varLoc == Location::Memory ? DataLocation::Memory : DataLocation::Storage;
+ {
+ switch (varLoc)
+ {
+ case Location::Memory:
+ typeLoc = DataLocation::Memory;
+ break;
+ case Location::Storage:
+ typeLoc = DataLocation::Storage;
+ break;
+ case Location::CallData:
+ fatalTypeError(_variable.location(),
+ "Variable cannot be declared as \"calldata\" (remove the \"calldata\" keyword)."
+ );
+ break;
+ default:
+ solAssert(false, "Unknown data location");
+ }
+ }
isPointer = !_variable.isStateVariable();
}
type = ref->copyForLocation(typeLoc, isPointer);
}
else if (varLoc != Location::Default && !ref)
- typeError(_variable.location(), "Storage location can only be given for array or struct types.");
+ typeError(_variable.location(), "Data location can only be given for array or struct types.");
_variable.annotation().type = type;
}
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp
index 30302908..60cde33c 100644
--- a/libsolidity/analysis/TypeChecker.cpp
+++ b/libsolidity/analysis/TypeChecker.cpp
@@ -351,7 +351,7 @@ void TypeChecker::annotateBaseConstructorArguments(
SourceLocation const* mainLocation = nullptr;
SecondarySourceLocation ssl;
-
+
if (
_currentContract.location().contains(previousNode->location()) ||
_currentContract.location().contains(_argumentNode->location())
diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h
index fa0d6921..d703ae53 100644
--- a/libsolidity/ast/AST.h
+++ b/libsolidity/ast/AST.h
@@ -656,7 +656,7 @@ private:
class VariableDeclaration: public Declaration
{
public:
- enum Location { Default, Storage, Memory };
+ enum Location { Default, Storage, Memory, CallData };
VariableDeclaration(
SourceLocation const& _sourceLocation,
diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp
index b8e00b60..b7855668 100644
--- a/libsolidity/ast/ASTJsonConverter.cpp
+++ b/libsolidity/ast/ASTJsonConverter.cpp
@@ -751,6 +751,8 @@ string ASTJsonConverter::location(VariableDeclaration::Location _location)
return "storage";
case VariableDeclaration::Location::Memory:
return "memory";
+ case VariableDeclaration::Location::CallData:
+ return "calldata";
default:
solAssert(false, "Unknown declaration location.");
}
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp
index 59668e1d..8620f283 100644
--- a/libsolidity/ast/Types.cpp
+++ b/libsolidity/ast/Types.cpp
@@ -1469,12 +1469,20 @@ string ReferenceType::stringForReferencePart() const
string ReferenceType::identifierLocationSuffix() const
{
string id;
- if (location() == DataLocation::Storage)
+ switch (location())
+ {
+ case DataLocation::Storage:
id += "_storage";
- else if (location() == DataLocation::Memory)
+ break;
+ case DataLocation::Memory:
id += "_memory";
- else
+ break;
+ case DataLocation::CallData:
id += "_calldata";
+ break;
+ default:
+ solAssert(false, "Unknown location returned by location()");
+ }
if (isPointer())
id += "_ptr";
return id;
diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp
index e2e1eebc..aec9ebbb 100644
--- a/libsolidity/parsing/Parser.cpp
+++ b/libsolidity/parsing/Parser.cpp
@@ -592,11 +592,22 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
else if (!type)
parserError(string("Location specifier needs explicit type name."));
else
- location = (
- token == Token::Memory ?
- VariableDeclaration::Location::Memory :
- VariableDeclaration::Location::Storage
- );
+ {
+ switch (token)
+ {
+ case Token::Storage:
+ location = VariableDeclaration::Location::Storage;
+ break;
+ case Token::Memory:
+ location = VariableDeclaration::Location::Memory;
+ break;
+ case Token::CallData:
+ location = VariableDeclaration::Location::CallData;
+ break;
+ default:
+ solAssert(false, "Unknown data location.");
+ }
+ }
}
else
break;
diff --git a/libsolidity/parsing/Token.h b/libsolidity/parsing/Token.h
index 4d7a7bc6..4d456550 100644
--- a/libsolidity/parsing/Token.h
+++ b/libsolidity/parsing/Token.h
@@ -173,6 +173,7 @@ namespace solidity
K(Return, "return", 0) \
K(Returns, "returns", 0) \
K(Storage, "storage", 0) \
+ K(CallData, "calldata", 0) \
K(Struct, "struct", 0) \
K(Throw, "throw", 0) \
K(Using, "using", 0) \
@@ -289,7 +290,7 @@ public:
static bool isShiftOp(Value op) { return (SHL <= op) && (op <= SHR); }
static bool isVisibilitySpecifier(Value op) { return isVariableVisibilitySpecifier(op) || op == External; }
static bool isVariableVisibilitySpecifier(Value op) { return op == Public || op == Private || op == Internal; }
- static bool isLocationSpecifier(Value op) { return op == Memory || op == Storage; }
+ static bool isLocationSpecifier(Value op) { return op == Memory || op == Storage || op == CallData; }
static bool isStateMutabilitySpecifier(Value op) { return op == Pure || op == Constant || op == View || op == Payable; }
static bool isEtherSubdenomination(Value op) { return op == SubWei || op == SubSzabo || op == SubFinney || op == SubEther; }
static bool isTimeSubdenomination(Value op) { return op == SubSecond || op == SubMinute || op == SubHour || op == SubDay || op == SubWeek || op == SubYear; }
@@ -348,7 +349,7 @@ public:
unsigned int secondNumber() const { return m_secondNumber; }
Token::Value token() const { return m_token; }
///if tokValue is set to true, then returns the actual token type name, otherwise, returns full type
- std::string toString(bool const& tokenValue = false) const
+ std::string toString(bool const& tokenValue = false) const
{
std::string name = Token::toString(m_token);
if (tokenValue || (firstNumber() == 0 && secondNumber() == 0))