aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2020-12-14 15:40:17 +0000
committerGitHub <noreply@github.com>2020-12-14 15:40:17 +0000
commit6e4b74fb77c45a6088e0cca22ec05c28c7f0b6dc (patch)
tree46eb33355b3d0351d4743d19d1d5c46ae9d5677c /gcc
parentcef34bd730d80b4664d8633e2cc27a64c5cae246 (diff)
parent52cc571b308d3d0103dd498fd277859e2116791a (diff)
downloadgcc-6e4b74fb77c45a6088e0cca22ec05c28c7f0b6dc.zip
gcc-6e4b74fb77c45a6088e0cca22ec05c28c7f0b6dc.tar.gz
gcc-6e4b74fb77c45a6088e0cca22ec05c28c7f0b6dc.tar.bz2
Merge pull request #62 from SimplyTheOther/master
Expansion code for cfg attributes, bug fixes and minor enhancements in parser
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/analysis/rust-scan.cc2
-rw-r--r--gcc/rust/analysis/rust-type-resolution.cc138
-rw-r--r--gcc/rust/analysis/rust-type-resolution.h4
-rw-r--r--gcc/rust/ast/rust-ast-full-test.cc504
-rw-r--r--gcc/rust/ast/rust-ast.h485
-rw-r--r--gcc/rust/ast/rust-expr.h1728
-rw-r--r--gcc/rust/ast/rust-item.h1532
-rw-r--r--gcc/rust/ast/rust-macro.h55
-rw-r--r--gcc/rust/ast/rust-path.h219
-rw-r--r--gcc/rust/ast/rust-pattern.h341
-rw-r--r--gcc/rust/ast/rust-stmt.h135
-rw-r--r--gcc/rust/ast/rust-type.h243
-rw-r--r--gcc/rust/backend/rust-compile.cc240
-rw-r--r--gcc/rust/expand/rust-macro-expand.cc3449
-rw-r--r--gcc/rust/expand/rust-macro-expand.h9
-rw-r--r--gcc/rust/parse/rust-parse-impl.h528
-rw-r--r--gcc/rust/parse/rust-parse.h9
-rw-r--r--gcc/rust/rust-session-manager.cc23
18 files changed, 7681 insertions, 1963 deletions
diff --git a/gcc/rust/analysis/rust-scan.cc b/gcc/rust/analysis/rust-scan.cc
index 402ac32..31c89e4 100644
--- a/gcc/rust/analysis/rust-scan.cc
+++ b/gcc/rust/analysis/rust-scan.cc
@@ -353,7 +353,7 @@ TopLevelScan::visit (AST::UseDeclaration &use_decl)
void
TopLevelScan::visit (AST::Function &function)
{
- functions[function.function_name] = &function;
+ functions[function.get_function_name ()] = &function;
}
void
diff --git a/gcc/rust/analysis/rust-type-resolution.cc b/gcc/rust/analysis/rust-type-resolution.cc
index 51c7380..f1edec8 100644
--- a/gcc/rust/analysis/rust-type-resolution.cc
+++ b/gcc/rust/analysis/rust-type-resolution.cc
@@ -165,10 +165,10 @@ void
TypeResolution::visit (AST::IdentifierExpr &ident_expr)
{
AST::Type *type = NULL;
- bool ok = scope.LookupType (ident_expr.ident, &type);
+ bool ok = scope.LookupType (ident_expr.get_ident (), &type);
if (!ok)
{
- rust_error_at (ident_expr.locus, "unknown identifier");
+ rust_error_at (ident_expr.get_locus (), "unknown identifier");
return;
}
@@ -242,7 +242,7 @@ void
TypeResolution::visit (AST::LiteralExpr &expr)
{
std::string type;
- switch (expr.literal.get_lit_type ())
+ switch (expr.get_lit_type ())
{
case AST::Literal::CHAR:
type = "char";
@@ -279,8 +279,8 @@ TypeResolution::visit (AST::LiteralExpr &expr)
if (type.empty ())
{
- rust_error_at (expr.locus, "unknown literal: %s",
- expr.literal.as_string ().c_str ());
+ rust_error_at (expr.get_locus (), "unknown literal: %s",
+ expr.get_literal ().as_string ().c_str ());
return;
}
@@ -289,7 +289,7 @@ TypeResolution::visit (AST::LiteralExpr &expr)
if (ok)
typeBuffer.push_back (val);
else
- rust_error_at (expr.locus, "unknown literal type: %s", type.c_str ());
+ rust_error_at (expr.get_locus (), "unknown literal type: %s", type.c_str ());
}
void
@@ -325,7 +325,7 @@ TypeResolution::visit (AST::ArithmeticOrLogicalExpr &expr)
expr.visit_lhs (*this);
if (typeBuffer.size () <= before)
{
- rust_error_at (expr.locus, "unable to determine lhs type");
+ rust_error_at (expr.get_locus (), "unable to determine lhs type");
return;
}
@@ -336,7 +336,7 @@ TypeResolution::visit (AST::ArithmeticOrLogicalExpr &expr)
expr.visit_rhs (*this);
if (typeBuffer.size () <= before)
{
- rust_error_at (expr.locus, "unable to determine rhs type");
+ rust_error_at (expr.get_locus (), "unable to determine rhs type");
return;
}
@@ -345,7 +345,7 @@ TypeResolution::visit (AST::ArithmeticOrLogicalExpr &expr)
// scope will require knowledge of the type
// do the lhsType and the rhsType match
- typesAreCompatible (lhsType, rhsType, expr.right_expr->get_locus_slow ());
+ typesAreCompatible (lhsType, rhsType, expr.get_right_expr ()->get_locus_slow ());
}
void
@@ -368,7 +368,7 @@ TypeResolution::visit (AST::AssignmentExpr &expr)
expr.visit_lhs (*this);
if (typeBuffer.size () <= before)
{
- rust_error_at (expr.locus, "unable to determine lhs type");
+ rust_error_at (expr.get_locus (), "unable to determine lhs type");
return;
}
@@ -379,7 +379,7 @@ TypeResolution::visit (AST::AssignmentExpr &expr)
expr.visit_rhs (*this);
if (typeBuffer.size () <= before)
{
- rust_error_at (expr.locus, "unable to determine rhs type");
+ rust_error_at (expr.get_locus (), "unable to determine rhs type");
return;
}
@@ -389,7 +389,7 @@ TypeResolution::visit (AST::AssignmentExpr &expr)
// do the lhsType and the rhsType match
if (!typesAreCompatible (lhsType, rhsType,
- expr.right_expr->get_locus_slow ()))
+ expr.get_right_expr ()->get_locus_slow ()))
return;
// is the lhs mutable?
@@ -465,7 +465,7 @@ TypeResolution::visit (AST::ArrayElemsCopied &elems)
void
TypeResolution::visit (AST::ArrayExpr &expr)
{
- auto elements = expr.get_internal_elements ();
+ auto& elements = expr.get_array_elems ();
auto before = typeBuffer.size ();
elements->accept_vis (*this);
@@ -526,7 +526,7 @@ TypeResolution::visit (AST::ArrayIndexExpr &expr)
return;
}
- typeBuffer.push_back (resolved->get_element_type ());
+ typeBuffer.push_back (resolved->get_elem_type ().get ());
}
void
@@ -548,15 +548,15 @@ TypeResolution::visit (AST::StructExprFieldIdentifier &field)
void
TypeResolution::visit (AST::StructExprFieldIdentifierValue &field)
{
- identifierBuffer = &field.field_name;
- field.value->accept_vis (*this);
+ identifierBuffer = std::unique_ptr<std::string> (new std::string (field.get_field_name ()));
+ field.get_value ()->accept_vis (*this);
}
void
TypeResolution::visit (AST::StructExprFieldIndexValue &field)
{
- tupleIndexBuffer = &field.index;
- field.value->accept_vis (*this);
+ tupleIndexBuffer = std::unique_ptr<int> (new int (field.get_index ()));
+ field.get_value ()->accept_vis (*this);
}
void
@@ -569,7 +569,7 @@ TypeResolution::visit (AST::StructExprStructFields &expr)
return;
}
- for (auto &field : expr.fields)
+ for (auto &field : expr.get_fields ())
{
identifierBuffer = NULL;
tupleIndexBuffer = NULL;
@@ -590,9 +590,9 @@ TypeResolution::visit (AST::StructExprStructFields &expr)
if (identifierBuffer != NULL)
{
AST::StructField *declField = NULL;
- for (auto &df : decl->fields)
+ for (auto &df : decl->get_fields ())
{
- if (identifierBuffer->compare (df.field_name) == 0)
+ if (identifierBuffer->compare (df.get_field_name ()) == 0)
{
declField = &df;
break;
@@ -606,7 +606,7 @@ TypeResolution::visit (AST::StructExprStructFields &expr)
return;
}
- if (!typesAreCompatible (declField->field_type.get (), inferedType,
+ if (!typesAreCompatible (declField->get_field_type ().get (), inferedType,
expr.get_locus_slow ()))
return;
}
@@ -614,9 +614,9 @@ TypeResolution::visit (AST::StructExprStructFields &expr)
else if (tupleIndexBuffer != NULL)
{
AST::StructField *declField = NULL;
- if (*tupleIndexBuffer < decl->fields.size ())
+ if (*tupleIndexBuffer < decl->get_fields ().size ())
{
- declField = &decl->fields[*tupleIndexBuffer];
+ declField = &decl->get_fields ()[*tupleIndexBuffer];
}
tupleIndexBuffer = NULL;
@@ -626,7 +626,7 @@ TypeResolution::visit (AST::StructExprStructFields &expr)
return;
}
- if (!typesAreCompatible (declField->field_type.get (), inferedType,
+ if (!typesAreCompatible (declField->get_field_type ().get (), inferedType,
expr.get_locus_slow ()))
return;
}
@@ -686,41 +686,41 @@ void
TypeResolution::visit (AST::CallExpr &expr)
{
// this look up should probably be moved to name resolution
- auto fndecl = lookupFndecl (expr.function.get ());
+ auto fndecl = lookupFndecl (expr.get_function_expr ().get ());
if (fndecl == NULL)
return;
// check num args match
- if (fndecl->function_params.size () != expr.params.size ())
+ if (fndecl->get_function_params ().size () != expr.get_params ().size ())
{
rust_error_at (expr.get_locus_slow (),
"differing number of arguments vs parameters to function");
return;
}
- typeBuffer.push_back (fndecl->return_type.get ());
+ typeBuffer.push_back (fndecl->get_return_type ().get ());
expr.fndeclRef = fndecl;
auto before = typeBuffer.size ();
- for (auto &item : expr.params)
+ for (auto &item : expr.get_params ())
item->accept_vis (*this);
auto numInferedParams = typeBuffer.size () - before;
- if (numInferedParams != expr.params.size ())
+ if (numInferedParams != expr.get_params ().size ())
{
- rust_error_at (expr.locus, "Failed to infer all parameters");
+ rust_error_at (expr.get_locus (), "Failed to infer all parameters");
return;
}
auto offs = numInferedParams - 1;
- for (auto it = fndecl->function_params.rbegin ();
- it != fndecl->function_params.rend (); ++it)
+ for (auto it = fndecl->get_function_params ().rbegin ();
+ it != fndecl->get_function_params ().rend (); ++it)
{
AST::Type *argument = typeBuffer.back ();
typeBuffer.pop_back ();
- if (!typesAreCompatible (it->type.get (), argument,
- expr.params[offs]->get_locus_slow ()))
+ if (!typesAreCompatible (it->get_type ().get (), argument,
+ expr.get_params ()[offs]->get_locus_slow ()))
return;
offs--;
}
@@ -740,7 +740,7 @@ void
TypeResolution::visit (AST::BlockExpr &expr)
{
scope.Push ();
- for (auto &stmt : expr.statements)
+ for (auto &stmt : expr.get_statements ())
{
stmt->accept_vis (*this);
}
@@ -780,11 +780,11 @@ TypeResolution::visit (AST::ReturnExpr &expr)
{
// Ensure the type of this matches the function
auto before = typeBuffer.size ();
- expr.get_expr ()->accept_vis (*this);
+ expr.get_returned_expr ()->accept_vis (*this);
if (typeBuffer.size () <= before)
{
- rust_error_at (expr.get_expr ()->get_locus_slow (),
+ rust_error_at (expr.get_returned_expr ()->get_locus_slow (),
"unable to determine type for return expr");
return;
}
@@ -796,14 +796,14 @@ TypeResolution::visit (AST::ReturnExpr &expr)
// this will again have issues with structs before we move to HIR
auto function = scope.CurrentFunction ();
- if (!function->has_function_return_type ())
+ if (!function->has_return_type ())
{
rust_error_at (expr.get_locus (), "return for void function %s",
function->as_string ().c_str ());
return;
}
- if (!typesAreCompatible (function->return_type.get (), inferedType,
+ if (!typesAreCompatible (function->get_return_type ().get (), inferedType,
expr.get_locus_slow ()))
{
return;
@@ -920,14 +920,14 @@ TypeResolution::visit (AST::Function &function)
{
// always emit the function with return type in the event of nil return type
// its a marker for a void function
- scope.InsertType (function.function_name, function.return_type.get ());
- scope.InsertFunction (function.function_name, &function);
+ scope.InsertType (function.get_function_name (), function.get_return_type ().get ());
+ scope.InsertFunction (function.get_function_name (), &function);
scope.PushFunction (&function);
scope.Push ();
- for (auto &param : function.function_params)
+ for (auto &param : function.get_function_params ())
{
- if (!isTypeInScope (param.type.get (), param.locus))
+ if (!isTypeInScope (param.get_type ().get (), param.get_locus ()))
{
scope.Pop ();
scope.PopFunction ();
@@ -935,10 +935,10 @@ TypeResolution::visit (AST::Function &function)
}
auto before = letPatternBuffer.size ();
- param.param_name->accept_vis (*this);
+ param.get_pattern ()->accept_vis (*this);
if (letPatternBuffer.size () <= before)
{
- rust_error_at (param.locus, "failed to analyse parameter name");
+ rust_error_at (param.get_locus (), "failed to analyse parameter name");
scope.Pop ();
scope.PopFunction ();
@@ -947,13 +947,13 @@ TypeResolution::visit (AST::Function &function)
auto paramName = letPatternBuffer.back ();
letPatternBuffer.pop_back ();
- scope.InsertType (paramName.variable_ident, param.type.get ());
+ scope.InsertType (paramName.get_ident (), param.get_type ().get ());
}
// ensure the return type is resolved
- if (function.has_function_return_type ())
+ if (function.has_return_type ())
{
- if (!isTypeInScope (function.return_type.get (), function.locus))
+ if (!isTypeInScope (function.get_return_type ().get (), function.get_locus ()))
{
scope.Pop ();
scope.PopFunction ();
@@ -962,7 +962,7 @@ TypeResolution::visit (AST::Function &function)
}
// walk the expression body
- for (auto &stmt : function.function_body->statements)
+ for (auto &stmt : function.get_definition ()->get_statements ())
{
stmt->accept_vis (*this);
}
@@ -982,9 +982,9 @@ TypeResolution::visit (AST::TypeAlias &type_alias)
void
TypeResolution::visit (AST::StructStruct &struct_item)
{
- for (auto &field : struct_item.fields)
+ for (auto &field : struct_item.get_fields ())
{
- if (!isTypeInScope (field.field_type.get (),
+ if (!isTypeInScope (field.get_field_type ().get (),
Linemap::unknown_location ()))
{
rust_fatal_error (Linemap::unknown_location (),
@@ -993,7 +993,7 @@ TypeResolution::visit (AST::StructStruct &struct_item)
}
}
- scope.InsertStruct (struct_item.struct_name, &struct_item);
+ scope.InsertStruct (struct_item.get_struct_name (), &struct_item);
}
void
@@ -1177,7 +1177,7 @@ TypeResolution::visit (AST::LetStmt &stmt)
scope.InsertLocal (stmt.as_string (), &stmt);
if (!stmt.has_init_expr () && !stmt.has_type ())
{
- rust_error_at (stmt.locus,
+ rust_error_at (stmt.get_locus (),
"E0282: type annotations or init expression needed");
return;
}
@@ -1186,12 +1186,12 @@ TypeResolution::visit (AST::LetStmt &stmt)
if (stmt.has_init_expr ())
{
auto before = typeBuffer.size ();
- stmt.init_expr->accept_vis (*this);
+ stmt.get_init_expr ()->accept_vis (*this);
if (typeBuffer.size () <= before)
{
rust_error_at (
- stmt.init_expr->get_locus_slow (),
+ stmt.get_init_expr ()->get_locus_slow (),
"unable to determine type for declaration from init expr");
return;
}
@@ -1201,7 +1201,7 @@ TypeResolution::visit (AST::LetStmt &stmt)
if (inferedType == NULL)
{
- rust_error_at (stmt.init_expr->get_locus_slow (),
+ rust_error_at (stmt.get_init_expr ()->get_locus_slow (),
"void type found for statement initialisation");
return;
}
@@ -1209,8 +1209,8 @@ TypeResolution::visit (AST::LetStmt &stmt)
if (stmt.has_type () && stmt.has_init_expr ())
{
- if (!typesAreCompatible (stmt.type.get (), inferedType,
- stmt.init_expr->get_locus_slow ()))
+ if (!typesAreCompatible (stmt.get_type ().get (), inferedType,
+ stmt.get_init_expr ()->get_locus_slow ()))
{
return;
}
@@ -1218,10 +1218,10 @@ TypeResolution::visit (AST::LetStmt &stmt)
else if (stmt.has_type ())
{
auto before = typeComparisonBuffer.size ();
- stmt.type->accept_vis (*this);
+ stmt.get_type ()->accept_vis (*this);
if (typeComparisonBuffer.size () <= before)
{
- rust_error_at (stmt.locus, "failed to understand type for lhs");
+ rust_error_at (stmt.get_locus (), "failed to understand type for lhs");
return;
}
auto typeString = typeComparisonBuffer.back ();
@@ -1241,7 +1241,7 @@ TypeResolution::visit (AST::LetStmt &stmt)
inferedType->accept_vis (*this);
if (typeComparisonBuffer.size () <= before)
{
- rust_error_at (stmt.locus, "failed to understand type for lhs");
+ rust_error_at (stmt.get_locus (), "failed to understand type for lhs");
return;
}
auto typeString = typeComparisonBuffer.back ();
@@ -1250,14 +1250,14 @@ TypeResolution::visit (AST::LetStmt &stmt)
// AST::Type *val = NULL;
// if (!scope.LookupType (typeString, &val))
// {
- // rust_error_at (stmt.locus, "Inferred unknown type: %s",
+ // rust_error_at (stmt.get_locus (), "Inferred unknown type: %s",
// inferedType->as_string ().c_str ());
// return;
// }
}
else
{
- rust_fatal_error (stmt.locus, "Failed to determine any type for LetStmt");
+ rust_fatal_error (stmt.get_locus (), "Failed to determine any type for LetStmt");
return;
}
@@ -1268,9 +1268,9 @@ TypeResolution::visit (AST::LetStmt &stmt)
}
// get all the names part of this declaration and add the types to the scope
- stmt.variables_pattern->accept_vis (*this);
+ stmt.get_pattern ()->accept_vis (*this);
for (auto &pattern : letPatternBuffer)
- scope.InsertType (pattern.variable_ident, inferedType);
+ scope.InsertType (pattern.get_ident (), inferedType);
letPatternBuffer.clear ();
}
@@ -1278,14 +1278,14 @@ TypeResolution::visit (AST::LetStmt &stmt)
void
TypeResolution::visit (AST::ExprStmtWithoutBlock &stmt)
{
- stmt.expr->accept_vis (*this);
+ stmt.get_expr ()->accept_vis (*this);
}
void
TypeResolution::visit (AST::ExprStmtWithBlock &stmt)
{
scope.Push ();
- stmt.expr->accept_vis (*this);
+ stmt.get_expr ()->accept_vis (*this);
auto localMap = scope.PeekLocals ();
for (auto &[_, value] : localMap)
{
@@ -1331,7 +1331,7 @@ TypeResolution::visit (AST::ReferenceType &type)
void
TypeResolution::visit (AST::ArrayType &type)
{
- typeComparisonBuffer.push_back (type.get_element_type ()->as_string ());
+ typeComparisonBuffer.push_back (type.get_elem_type ()->as_string ());
}
void
diff --git a/gcc/rust/analysis/rust-type-resolution.h b/gcc/rust/analysis/rust-type-resolution.h
index 0fef2ae..2f61a39 100644
--- a/gcc/rust/analysis/rust-type-resolution.h
+++ b/gcc/rust/analysis/rust-type-resolution.h
@@ -326,8 +326,8 @@ private:
bool isTypeInScope (AST::Type *type, Location locus);
TypeScoping scope;
- std::string *identifierBuffer;
- int *tupleIndexBuffer;
+ std::unique_ptr<std::string> identifierBuffer;
+ std::unique_ptr<int> tupleIndexBuffer;
};
} // namespace Analysis
diff --git a/gcc/rust/ast/rust-ast-full-test.cc b/gcc/rust/ast/rust-ast-full-test.cc
index 0cdac5f..030b0b3 100644
--- a/gcc/rust/ast/rust-ast-full-test.cc
+++ b/gcc/rust/ast/rust-ast-full-test.cc
@@ -171,13 +171,33 @@ Attribute::as_string () const
{
std::string path_str = path.as_string ();
if (attr_input == nullptr)
- {
- return path_str;
- }
+ return path_str;
else
- {
- return path_str + attr_input->as_string ();
- }
+ return path_str + attr_input->as_string ();
+}
+
+// Copy constructor must deep copy attr_input as unique pointer
+Attribute::Attribute (Attribute const &other)
+ : path (other.path), locus (other.locus)
+{
+ // guard to protect from null pointer dereference
+ if (other.attr_input != nullptr)
+ attr_input = other.attr_input->clone_attr_input ();
+}
+
+// overload assignment operator to use custom clone method
+Attribute &
+Attribute::operator= (Attribute const &other)
+{
+ path = other.path;
+ locus = other.locus;
+ // guard to protect from null pointer dereference
+ if (other.attr_input != nullptr)
+ attr_input = other.attr_input->clone_attr_input ();
+ else
+ attr_input = nullptr;
+
+ return *this;
}
std::string
@@ -307,7 +327,13 @@ std::string
VisItem::as_string () const
{
// FIXME: can't do formatting on string to make identation occur.
- std::string str = Item::as_string ();
+ std::string str;
+
+ if (!outer_attrs.empty ())
+ {
+ for (const auto &attr : outer_attrs)
+ str += attr.as_string () + "\n";
+ }
if (has_visibility ())
{
@@ -318,7 +344,7 @@ VisItem::as_string () const
}
// Creates a string that reflects the outer attributes stored.
-std::string
+/*std::string
Item::as_string () const
{
std::string str;
@@ -332,7 +358,7 @@ Item::as_string () const
}
return str;
-}
+}*/
std::string
Module::as_string () const
@@ -654,33 +680,23 @@ Method::as_string () const
else
{
for (const auto &param : function_params)
- {
- str += "\n " + param.as_string ();
- }
+ str += "\n " + param.as_string ();
}
str += "\n Return type: ";
if (has_return_type ())
- {
- str += return_type->as_string ();
- }
+ str += return_type->as_string ();
else
- {
- str += "none (void)";
- }
+ str += "none (void)";
str += "\n Where clause: ";
if (has_where_clause ())
- {
- str += where_clause.as_string ();
- }
+ str += where_clause.as_string ();
else
- {
- str += "none";
- }
+ str += "none";
str += "\n Block expr (body): \n ";
- str += expr->as_string ();
+ str += function_body->as_string ();
return str;
}
@@ -1089,7 +1105,7 @@ Function::as_string () const
if ("" != qstr)
str += qstr + " ";
- if (has_function_return_type ())
+ if (has_return_type ())
{
// DEBUG: null pointer check
if (return_type == nullptr)
@@ -1154,9 +1170,7 @@ Function::as_string () const
}
if (has_where_clause ())
- {
- str += " where " + where_clause.as_string ();
- }
+ str += " where " + where_clause.as_string ();
str += "\n";
@@ -1187,9 +1201,7 @@ WhereClause::as_string () const
else
{
for (const auto &item : where_clause_items)
- {
- str += "\n " + item->as_string ();
- }
+ str += "\n " + item->as_string ();
}
return str;
@@ -1214,9 +1226,7 @@ BlockExpr::as_string () const
/* note that this does not print them with "inner attribute" syntax -
* just the body */
for (const auto &attr : inner_attrs)
- {
- str += "\n" + indent_spaces (stay) + attr.as_string ();
- }
+ str += "\n" + indent_spaces (stay) + attr.as_string ();
}
// statements
@@ -1246,13 +1256,9 @@ BlockExpr::as_string () const
// final expression
str += "\n" + indent_spaces (stay) + "final expression: ";
if (expr == nullptr)
- {
- str += "none";
- }
+ str += "none";
else
- {
- str += "\n" + expr->as_string ();
- }
+ str += "\n" + expr->as_string ();
str += "\n" + indent_spaces (out) + "}";
return str;
@@ -1264,9 +1270,7 @@ TraitImpl::as_string () const
std::string str = VisItem::as_string ();
if (has_unsafe)
- {
- str += "unsafe ";
- }
+ str += "unsafe ";
str += "impl ";
@@ -1279,20 +1283,14 @@ TraitImpl::as_string () const
else
{
for (const auto &param : generic_params)
- {
- str += "\n " + param->as_string ();
- }
+ str += "\n " + param->as_string ();
}
str += "\n Has exclam: ";
if (has_exclam)
- {
- str += "true";
- }
+ str += "true";
else
- {
- str += "false";
- }
+ str += "false";
str += "\n TypePath (to trait): " + trait_path.as_string ();
@@ -1300,13 +1298,9 @@ TraitImpl::as_string () const
str += "\n Where clause: ";
if (!has_where_clause ())
- {
- str += "none";
- }
+ str += "none";
else
- {
- str += where_clause.as_string ();
- }
+ str += where_clause.as_string ();
// inner attributes
str += "\n inner attributes: ";
@@ -1319,9 +1313,7 @@ TraitImpl::as_string () const
/* note that this does not print them with "inner attribute" syntax -
* just the body */
for (const auto &attr : inner_attrs)
- {
- str += "\n " + attr.as_string ();
- }
+ str += "\n " + attr.as_string ();
}
str += "\n trait impl items: ";
@@ -1332,9 +1324,7 @@ TraitImpl::as_string () const
else
{
for (const auto &item : impl_items)
- {
- str += "\n " + item->as_string ();
- }
+ str += "\n " + item->as_string ();
}
return str;
@@ -1384,8 +1374,14 @@ TypeAlias::as_string () const
std::string
MacroInvocationSemi::as_string () const
{
+ std::string str;
+
// get outer attrs
- std::string str = MacroItem::as_string ();
+ if (!outer_attrs.empty ())
+ {
+ for (const auto &attr : outer_attrs)
+ str += attr.as_string () + "\n";
+ }
str += "\n" + path.as_string () + "!";
@@ -1444,9 +1440,7 @@ ExternBlock::as_string () const
/* note that this does not print them with "inner attribute" syntax -
* just the body */
for (const auto &attr : inner_attrs)
- {
- str += "\n " + attr.as_string ();
- }
+ str += "\n " + attr.as_string ();
}
str += "\n external items: ";
@@ -1457,9 +1451,7 @@ ExternBlock::as_string () const
else
{
for (const auto &item : extern_items)
- {
- str += "\n " + item->as_string ();
- }
+ str += "\n " + item->as_string ();
}
return str;
@@ -1482,7 +1474,16 @@ MacroRule::as_string () const
std::string
MacroRulesDefinition::as_string () const
{
- std::string str ("macro_rules!");
+ std::string str;
+
+ // get outer attrs
+ if (!outer_attrs.empty ())
+ {
+ for (const auto &attr : outer_attrs)
+ str += attr.as_string () + "\n";
+ }
+
+ str += "macro_rules!";
str += rule_name;
@@ -1494,9 +1495,7 @@ MacroRulesDefinition::as_string () const
else
{
for (const auto &rule : rules)
- {
- str += "\n " + rule.as_string ();
- }
+ str += "\n " + rule.as_string ();
}
str += "\n Delim type: ";
@@ -1531,9 +1530,7 @@ PathInExpression::as_string () const
std::string str;
if (has_opening_scope_resolution)
- {
- str = "::";
- }
+ str = "::";
return str + PathPattern::as_string ();
}
@@ -1564,9 +1561,7 @@ ClosureParam::as_string () const
std::string str (pattern->as_string ());
if (has_type_given ())
- {
- str += " : " + type->as_string ();
- }
+ str += " : " + type->as_string ();
return str;
}
@@ -1576,13 +1571,9 @@ ClosureExpr::as_string () const
{
std::string str ("ClosureExpr:\n Has move: ");
if (has_move)
- {
- str += "true";
- }
+ str += "true";
else
- {
- str += "false";
- }
+ str += "false";
str += "\n Params: ";
if (params.empty ())
@@ -1592,9 +1583,7 @@ ClosureExpr::as_string () const
else
{
for (const auto &param : params)
- {
- str += "\n " + param.as_string ();
- }
+ str += "\n " + param.as_string ();
}
return str;
@@ -1618,9 +1607,7 @@ PathPattern::as_string () const
std::string str;
for (const auto &segment : segments)
- {
- str += segment.as_string () + "::";
- }
+ str += segment.as_string () + "::";
// basically a hack - remove last two characters of string (remove final ::)
str.erase (str.length () - 2);
@@ -1635,9 +1622,7 @@ QualifiedPathType::as_string () const
str += type_to_invoke_on->as_string ();
if (has_as_clause ())
- {
- str += " as " + trait_path.as_string ();
- }
+ str += " as " + trait_path.as_string ();
return str + ">";
}
@@ -1654,14 +1639,10 @@ BorrowExpr::as_string () const
std::string str ("&");
if (double_borrow)
- {
- str += "&";
- }
+ str += "&";
if (is_mut)
- {
- str += "mut ";
- }
+ str += "mut ";
str += main_or_left_expr->as_string ();
@@ -1673,10 +1654,8 @@ ReturnExpr::as_string () const
{
std::string str ("return ");
- if (has_return_expr ())
- {
- str += return_expr->as_string ();
- }
+ if (has_returned_expr ())
+ str += return_expr->as_string ();
return str;
}
@@ -1697,9 +1676,7 @@ GroupedExpr::as_string () const
/* note that this does not print them with "inner attribute" syntax -
* just the body */
for (const auto &attr : inner_attrs)
- {
- str += "\n " + attr.as_string ();
- }
+ str += "\n " + attr.as_string ();
}
str += "\n Expr in parens: " + expr_in_parens->as_string ();
@@ -1719,9 +1696,7 @@ ContinueExpr::as_string () const
std::string str ("continue ");
if (has_label ())
- {
- str += label.as_string ();
- }
+ str += label.as_string ();
return str;
}
@@ -1856,9 +1831,7 @@ MethodCallExpr::as_string () const
for (const auto &param : params)
{
if (param == nullptr)
- {
- return "ERROR_MARK_STRING - method call expr param is null";
- }
+ return "ERROR_MARK_STRING - method call expr param is null";
str += "\n " + param->as_string ();
}
@@ -1997,9 +1970,7 @@ IfLetExpr::as_string () const
else
{
for (const auto &pattern : match_arm_patterns)
- {
- str += "\n " + pattern->as_string ();
- }
+ str += "\n " + pattern->as_string ();
}
str += "\n Scrutinee expr: " + value->as_string ();
@@ -2188,9 +2159,7 @@ CallExpr::as_string () const
for (const auto &param : params)
{
if (param == nullptr)
- {
- return "ERROR_MARK_STRING - call expr param is null";
- }
+ return "ERROR_MARK_STRING - call expr param is null";
str += "\n " + param->as_string ();
}
@@ -2206,13 +2175,9 @@ WhileLoopExpr::as_string () const
str += "\n Label: ";
if (!has_loop_label ())
- {
- str += "none";
- }
+ str += "none";
else
- {
- str += loop_label.as_string ();
- }
+ str += loop_label.as_string ();
str += "\n Conditional expr: " + condition->as_string ();
@@ -2228,13 +2193,9 @@ WhileLetLoopExpr::as_string () const
str += "\n Label: ";
if (!has_loop_label ())
- {
- str += "none";
- }
+ str += "none";
else
- {
- str += loop_label.as_string ();
- }
+ str += loop_label.as_string ();
str += "\n Match arm patterns: ";
if (match_arm_patterns.empty ())
@@ -2244,12 +2205,10 @@ WhileLetLoopExpr::as_string () const
else
{
for (const auto &pattern : match_arm_patterns)
- {
- str += "\n " + pattern->as_string ();
- }
+ str += "\n " + pattern->as_string ();
}
- str += "\n Scrutinee expr: " + condition->as_string ();
+ str += "\n Scrutinee expr: " + scrutinee->as_string ();
str += "\n Loop block: " + loop_block->as_string ();
@@ -2263,13 +2222,9 @@ LoopExpr::as_string () const
str += "\n Label: ";
if (!has_loop_label ())
- {
- str += "none";
- }
+ str += "none";
else
- {
- str += loop_label.as_string ();
- }
+ str += loop_label.as_string ();
str += "\n Loop block: " + loop_block->as_string ();
@@ -2292,20 +2247,14 @@ ArrayExpr::as_string () const
/* note that this does not print them with "inner attribute" syntax -
* just the body */
for (const auto &attr : inner_attrs)
- {
- str += "\n " + attr.as_string ();
- }
+ str += "\n " + attr.as_string ();
}
str += "\n Array elems: ";
if (!has_array_elems ())
- {
- str += "none";
- }
+ str += "none";
else
- {
- str += internal_elements->as_string ();
- }
+ str += internal_elements->as_string ();
return str;
}
@@ -2322,14 +2271,10 @@ BreakExpr::as_string () const
std::string str ("break ");
if (has_label ())
- {
- str += label.as_string () + " ";
- }
+ str += label.as_string () + " ";
if (has_break_expr ())
- {
- str += break_expr->as_string ();
- }
+ str += break_expr->as_string ();
return str;
}
@@ -2354,9 +2299,7 @@ MatchArm::as_string () const
/* note that this does not print them with "outer attribute" syntax -
* just the body */
for (const auto &attr : outer_attrs)
- {
- str += "\n " + attr.as_string ();
- }
+ str += "\n " + attr.as_string ();
}
str += "\nPatterns: ";
@@ -2367,20 +2310,14 @@ MatchArm::as_string () const
else
{
for (const auto &pattern : match_arm_patterns)
- {
- str += "\n " + pattern->as_string ();
- }
+ str += "\n " + pattern->as_string ();
}
str += "\nGuard expr: ";
if (!has_match_arm_guard ())
- {
- str += "none";
- }
+ str += "none";
else
- {
- str += guard_expr->as_string ();
- }
+ str += guard_expr->as_string ();
return str;
}
@@ -3694,9 +3631,7 @@ StructExprTuple::as_string () const
/* note that this does not print them with "inner attribute" syntax -
* just the body */
for (const auto &attr : inner_attrs)
- {
- str += "\n" + indent_spaces (stay) + attr.as_string ();
- }
+ str += "\n" + indent_spaces (stay) + attr.as_string ();
}
indent_spaces (out);
indent_spaces (out);
@@ -3722,9 +3657,7 @@ StructExprStruct::as_string () const
/* note that this does not print them with "inner attribute" syntax -
* just the body */
for (const auto &attr : inner_attrs)
- {
- str += "\n " + attr.as_string ();
- }
+ str += "\n " + attr.as_string ();
}
return str;
@@ -3734,13 +3667,9 @@ std::string
StructBase::as_string () const
{
if (base_struct != nullptr)
- {
- return base_struct->as_string ();
- }
+ return base_struct->as_string ();
else
- {
- return "ERROR_MARK_STRING - invalid struct base had as string applied";
- }
+ return "ERROR_MARK_STRING - invalid struct base had as string applied";
}
std::string
@@ -3775,25 +3704,59 @@ StructExprStructFields::as_string () const
else
{
for (const auto &field : fields)
- {
- str += "\n " + field->as_string ();
- }
+ str += "\n " + field->as_string ();
}
str += "\n Struct base: ";
if (!has_struct_base ())
+ str += "none";
+ else
+ str += struct_base.as_string ();
+
+ return str;
+}
+
+std::string
+EnumExprStruct::as_string () const
+{
+ std::string str ("StructExprStruct (or subclass): ");
+
+ str += "\n Path: " + get_enum_variant_path ().as_string ();
+
+ str += "\n Fields: ";
+ if (fields.empty ())
{
str += "none";
}
else
{
- str += struct_base.as_string ();
+ for (const auto &field : fields)
+ str += "\n " + field->as_string ();
}
return str;
}
std::string
+EnumExprFieldWithVal::as_string () const
+{
+ // used to get value string
+ return value->as_string ();
+}
+
+std::string
+EnumExprFieldIdentifierValue::as_string () const
+{
+ return field_name + " : " + EnumExprFieldWithVal::as_string ();
+}
+
+std::string
+EnumExprFieldIndexValue::as_string () const
+{
+ return std::to_string (index) + " : " + EnumExprFieldWithVal::as_string ();
+}
+
+std::string
EnumItem::as_string () const
{
// outer attributes
@@ -3807,9 +3770,7 @@ EnumItem::as_string () const
/* note that this does not print them with "outer attribute" syntax -
* just the body */
for (const auto &attr : outer_attrs)
- {
- str += "\n " + attr.as_string ();
- }
+ str += "\n " + attr.as_string ();
}
str += "\n" + variant_name;
@@ -3942,6 +3903,7 @@ EnumItemDiscriminant::as_string () const
return str;
}
+#if 0
std::string
ExternalItem::as_string () const
{
@@ -3956,9 +3918,7 @@ ExternalItem::as_string () const
/* note that this does not print them with "outer attribute" syntax -
* just the body */
for (const auto &attr : outer_attrs)
- {
str += "\n " + attr.as_string ();
- }
}
// start visibility on new line and with a space
@@ -3966,21 +3926,35 @@ ExternalItem::as_string () const
return str;
}
+#endif
std::string
ExternalStaticItem::as_string () const
{
- std::string str = ExternalItem::as_string ();
+ // outer attributes
+ std::string str = "outer attributes: ";
+ if (outer_attrs.empty ())
+ {
+ str += "none";
+ }
+ else
+ {
+ /* note that this does not print them with "outer attribute" syntax -
+ * just the body */
+ for (const auto &attr : outer_attrs)
+ str += "\n " + attr.as_string ();
+ }
+
+ // start visibility on new line and with a space
+ str += "\n" + visibility.as_string () + " ";
str += "static ";
if (has_mut)
- {
- str += "mut ";
- }
+ str += "mut ";
// add name
- str += get_item_name ();
+ str += item_name;
// add type on new line
str += "\n Type: " + item_type->as_string ();
@@ -3991,12 +3965,27 @@ ExternalStaticItem::as_string () const
std::string
ExternalFunctionItem::as_string () const
{
- std::string str = ExternalItem::as_string ();
+ // outer attributes
+ std::string str = "outer attributes: ";
+ if (outer_attrs.empty ())
+ {
+ str += "none";
+ }
+ else
+ {
+ /* note that this does not print them with "outer attribute" syntax -
+ * just the body */
+ for (const auto &attr : outer_attrs)
+ str += "\n " + attr.as_string ();
+ }
+
+ // start visibility on new line and with a space
+ str += "\n" + visibility.as_string () + " ";
str += "fn ";
// add name
- str += get_item_name ();
+ str += item_name;
// generic params
str += "\n Generic params: ";
@@ -4024,19 +4013,28 @@ ExternalFunctionItem::as_string () const
// function params
str += "\n Function params: ";
- if (function_params.empty ())
+ if (function_params.empty () && !has_variadics)
{
str += "none";
}
else
{
for (const auto &param : function_params)
- {
- str += "\n " + param.as_string ();
- }
+ str += "\n " + param.as_string ();
+
if (has_variadics)
{
- str += "\n .. (variadic)";
+ str += "\n variadic outer attrs: ";
+ if (has_variadic_outer_attrs ())
+ {
+ for (const auto &attr : variadic_outer_attrs)
+ str += "\n " + attr.as_string ();
+ }
+ else
+ {
+ str += "none";
+ }
+ str += "\n ... (variadic)";
}
}
@@ -4046,13 +4044,9 @@ ExternalFunctionItem::as_string () const
// where clause
str += "\n Where clause: ";
if (has_where_clause ())
- {
- str += where_clause.as_string ();
- }
+ str += where_clause.as_string ();
else
- {
- str += "none";
- }
+ str += "none";
return str;
}
@@ -4060,7 +4054,19 @@ ExternalFunctionItem::as_string () const
std::string
NamedFunctionParam::as_string () const
{
- std::string str = name;
+ std::string str = "outer attributes: ";
+
+ if (!has_outer_attrs ())
+ {
+ str += "none";
+ }
+ else
+ {
+ for (const auto &attr : outer_attrs)
+ str += "\n " + attr.as_string ();
+ }
+
+ str += "\n" + name;
str += "\n Type: " + param_type->as_string ();
@@ -4730,7 +4736,8 @@ MacroParser::parse_meta_item_inner ()
std::vector<MetaNameValueStr> meta_name_value_str_items;
for (const auto &item : meta_items)
{
- std::unique_ptr<MetaNameValueStr> converted_item = item->to_meta_name_value_str ();
+ std::unique_ptr<MetaNameValueStr> converted_item
+ = item->to_meta_name_value_str ();
if (converted_item == nullptr)
{
meta_name_value_str_items.clear ();
@@ -5048,18 +5055,21 @@ MacroParser::parse_meta_item_lit ()
bool
AttrInputMetaItemContainer::check_cfg_predicate (const Session &session) const
{
- /* cfg value of container is purely based on cfg of each inner item - all
- * must be true */
- for (const auto &inner_item : items)
+ /* NOTE: assuming that only first item must be true - cfg should only have one
+ * item, and cfg_attr only has first item as predicate. TODO ensure that this
+ * is correct. */
+ if (items.empty ())
+ return false;
+
+ return items[0]->check_cfg_predicate (session);
+
+ /*for (const auto &inner_item : items)
{
if (!inner_item->check_cfg_predicate (session))
return false;
}
- /* TODO: as far as I can tell, there should only be a single element to
- * check here, so ensure there is only a single element in items too? */
-
- return true;
+ return true;*/
}
bool
@@ -5346,6 +5356,62 @@ MetaItemPathLit::to_attribute () const
new AttrInputLiteral (lit)));
}
+std::vector<Attribute>
+AttrInputMetaItemContainer::separate_cfg_attrs () const
+{
+ rust_assert (!items.empty ());
+
+ if (items.size () == 1)
+ return {};
+
+ std::vector<Attribute> attrs;
+ attrs.reserve (items.size () - 1);
+
+ for (auto it = items.begin () + 1; it != items.end (); ++it)
+ {
+ Attribute attr = (*it)->to_attribute ();
+ if (attr.is_empty ())
+ {
+ // TODO should this be an error that causes us to chuck out
+ // everything?
+ continue;
+ }
+ attrs.push_back (std::move (attr));
+ }
+
+ attrs.shrink_to_fit ();
+ return attrs;
+}
+
+bool
+Attribute::check_cfg_predicate (const Session &session)
+{
+ /* assume that cfg predicate actually can exist, i.e. attribute has cfg or
+ * cfg_attr path */
+ if (!has_attr_input ()
+ || (path.as_string () != "cfg" && path.as_string () != "cfg_attr"))
+ return false;
+
+ // TODO: maybe replace with storing a "has been parsed" variable?
+ parse_attr_to_meta_item ();
+ // can't be const because of this anyway
+
+ return attr_input->check_cfg_predicate (session);
+}
+
+std::vector<Attribute>
+Attribute::separate_cfg_attrs ()
+{
+ if (!has_attr_input () || path.as_string () != "cfg_attr")
+ return {};
+
+ // TODO: maybe replace with storing a "has been parsed" variable?
+ parse_attr_to_meta_item ();
+ // can't be const because of this anyway
+
+ return attr_input->separate_cfg_attrs ();
+}
+
/* Visitor implementations - these are short but inlining can't happen anyway
* due to virtual functions and I didn't want to make the ast header includes
* any longer than they already are. */
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index ad3722f..bdc1f12 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -62,32 +62,6 @@ Location?
};*/
// decided to not have node as a "node" would never need to be stored
-// Attribute body - abstract base class
-class AttrInput
-{
-public:
- virtual ~AttrInput () {}
-
- // Unique pointer custom clone function
- std::unique_ptr<AttrInput> clone_attr_input () const
- {
- return std::unique_ptr<AttrInput> (clone_attr_input_impl ());
- }
-
- virtual std::string as_string () const = 0;
-
- virtual void accept_vis (ASTVisitor &vis) = 0;
-
- virtual bool check_cfg_predicate (const Session &session) const = 0;
-
- // Parse attribute input to meta item, if possible
- virtual AttrInput *parse_to_meta_item () const { return nullptr; }
-
-protected:
- // pure virtual clone implementation
- virtual AttrInput *clone_attr_input_impl () const = 0;
-};
-
// forward decl for use in token tree method
class Token;
@@ -109,7 +83,7 @@ public:
/* Converts token tree to a flat token stream. Tokens must be pointer to avoid
* mutual dependency with Token. */
- virtual std::vector<std::unique_ptr<Token>> to_token_stream () const = 0;
+ virtual std::vector<std::unique_ptr<Token> > to_token_stream () const = 0;
protected:
// pure virtual clone implementation
@@ -219,7 +193,7 @@ public:
void accept_vis (ASTVisitor &vis) override;
// Return copy of itself but in token stream form.
- std::vector<std::unique_ptr<Token>> to_token_stream () const override;
+ std::vector<std::unique_ptr<Token> > to_token_stream () const override;
TokenId get_id () const { return token_id; }
@@ -279,95 +253,6 @@ public:
bool is_error () const { return value_as_string == ""; }
};
-// A token tree with delimiters
-class DelimTokenTree : public TokenTree, public AttrInput
-{
- DelimType delim_type;
- std::vector<std::unique_ptr<TokenTree>> token_trees;
- Location locus;
-
-protected:
- DelimTokenTree *clone_delim_tok_tree_impl () const
- {
- return new DelimTokenTree (*this);
- }
-
- /* Use covariance to implement clone function as returning a DelimTokenTree
- * object */
- DelimTokenTree *clone_attr_input_impl () const override
- {
- return clone_delim_tok_tree_impl ();
- }
-
- /* Use covariance to implement clone function as returning a DelimTokenTree
- * object */
- DelimTokenTree *clone_token_tree_impl () const override
- {
- return clone_delim_tok_tree_impl ();
- }
-
-public:
- DelimTokenTree (DelimType delim_type,
- std::vector<std::unique_ptr<TokenTree>> token_trees
- = std::vector<std::unique_ptr<TokenTree>> (),
- Location locus = Location ())
- : delim_type (delim_type), token_trees (std::move (token_trees)),
- locus (locus)
- {}
-
- // Copy constructor with vector clone
- DelimTokenTree (DelimTokenTree const &other)
- : delim_type (other.delim_type), locus (other.locus)
- {
- token_trees.reserve (other.token_trees.size ());
- for (const auto &e : other.token_trees)
- token_trees.push_back (e->clone_token_tree ());
- }
-
- // overloaded assignment operator with vector clone
- DelimTokenTree &operator= (DelimTokenTree const &other)
- {
- delim_type = other.delim_type;
- locus = other.locus;
-
- token_trees.reserve (other.token_trees.size ());
- for (const auto &e : other.token_trees)
- token_trees.push_back (e->clone_token_tree ());
-
- return *this;
- }
-
- // move constructors
- DelimTokenTree (DelimTokenTree &&other) = default;
- DelimTokenTree &operator= (DelimTokenTree &&other) = default;
-
- static DelimTokenTree create_empty () { return DelimTokenTree (PARENS); }
-
- std::string as_string () const override;
-
- void accept_vis (ASTVisitor &vis) override;
-
- bool
- check_cfg_predicate (const Session &session ATTRIBUTE_UNUSED) const override
- {
- // this should never be called - should be converted first
- return false;
- }
-
- AttrInput *parse_to_meta_item () const override;
-
- std::vector<std::unique_ptr<Token>> to_token_stream () const override;
-
- std::unique_ptr<DelimTokenTree> clone_delim_token_tree () const
- {
- return std::unique_ptr<DelimTokenTree> (clone_delim_tok_tree_impl ());
- }
-};
-
-/* Forward decl - definition moved to rust-expr.h as it requires LiteralExpr to
- * be defined */
-class AttrInputLiteral;
-
/* TODO: move applicable stuff into here or just don't include it because
* nothing uses it A segment of a path (maybe) */
class PathSegment
@@ -442,7 +327,7 @@ public:
// does this need visitor if not polymorphic? probably not
// path-to-string comparison operator
- bool operator== (const std::string &rhs)
+ bool operator== (const std::string &rhs) const
{
return !has_opening_scope_resolution && segments.size () == 1
&& segments[0].as_string () == rhs;
@@ -460,6 +345,9 @@ public:
}
};
+// forward decl for Attribute
+class AttrInput;
+
// aka Attr
// Attribute AST representation
struct Attribute
@@ -488,15 +376,17 @@ public:
~Attribute () = default;
// Copy constructor must deep copy attr_input as unique pointer
- Attribute (Attribute const &other) : path (other.path), locus (other.locus)
+ /*Attribute (Attribute const &other) : path (other.path), locus (other.locus)
{
// guard to protect from null pointer dereference
if (other.attr_input != nullptr)
attr_input = other.attr_input->clone_attr_input ();
- }
+ }*/
+ // no point in being defined inline as requires virtual call anyway
+ Attribute (const Attribute &other);
// overload assignment operator to use custom clone method
- Attribute &operator= (Attribute const &other)
+ /*Attribute &operator= (Attribute const &other)
{
path = other.path;
locus = other.locus;
@@ -505,7 +395,9 @@ public:
attr_input = other.attr_input->clone_attr_input ();
return *this;
- }
+ }*/
+ // no point in being defined inline as requires virtual call anyway
+ Attribute &operator= (const Attribute &other);
// default move semantics
Attribute (Attribute &&other) = default;
@@ -581,29 +473,18 @@ public:
std::string as_string () const;
// TODO: does this require visitor pattern as not polymorphic?
-
- // Maybe change to const-reference in future
- SimplePath get_path () const { return path; }
+
+ const SimplePath &get_path () const { return path; }
+ SimplePath &get_path () { return path; }
// Call to parse attribute body to meta item syntax.
void parse_attr_to_meta_item ();
/* Determines whether cfg predicate is true and item with attribute should not
* be stripped. */
- bool check_cfg_predicate (const Session &session)
- {
- /* assume that cfg predicate actually can exist, i.e. attribute has cfg or
- * cfg_attr path */
-
- if (!has_attr_input ())
- return false;
+ bool check_cfg_predicate (const Session &session);
- // TODO: maybe replace with storing a "has been parsed" variable?
- parse_attr_to_meta_item ();
- // can't be const because of this anyway
-
- return attr_input->check_cfg_predicate (session);
- }
+ std::vector<Attribute> separate_cfg_attrs ();
protected:
// not virtual as currently no subclasses of Attribute, but could be in future
@@ -613,6 +494,122 @@ protected:
}
};
+// Attribute body - abstract base class
+class AttrInput
+{
+public:
+ virtual ~AttrInput () {}
+
+ // Unique pointer custom clone function
+ std::unique_ptr<AttrInput> clone_attr_input () const
+ {
+ return std::unique_ptr<AttrInput> (clone_attr_input_impl ());
+ }
+
+ virtual std::string as_string () const = 0;
+
+ virtual void accept_vis (ASTVisitor &vis) = 0;
+
+ virtual bool check_cfg_predicate (const Session &session) const = 0;
+
+ // Parse attribute input to meta item, if possible
+ virtual AttrInput *parse_to_meta_item () const { return nullptr; }
+
+ virtual std::vector<Attribute> separate_cfg_attrs () const { return {}; }
+
+protected:
+ // pure virtual clone implementation
+ virtual AttrInput *clone_attr_input_impl () const = 0;
+};
+
+// A token tree with delimiters
+class DelimTokenTree : public TokenTree, public AttrInput
+{
+ DelimType delim_type;
+ std::vector<std::unique_ptr<TokenTree> > token_trees;
+ Location locus;
+
+protected:
+ DelimTokenTree *clone_delim_tok_tree_impl () const
+ {
+ return new DelimTokenTree (*this);
+ }
+
+ /* Use covariance to implement clone function as returning a DelimTokenTree
+ * object */
+ DelimTokenTree *clone_attr_input_impl () const override
+ {
+ return clone_delim_tok_tree_impl ();
+ }
+
+ /* Use covariance to implement clone function as returning a DelimTokenTree
+ * object */
+ DelimTokenTree *clone_token_tree_impl () const override
+ {
+ return clone_delim_tok_tree_impl ();
+ }
+
+public:
+ DelimTokenTree (DelimType delim_type,
+ std::vector<std::unique_ptr<TokenTree> > token_trees
+ = std::vector<std::unique_ptr<TokenTree> > (),
+ Location locus = Location ())
+ : delim_type (delim_type), token_trees (std::move (token_trees)),
+ locus (locus)
+ {}
+
+ // Copy constructor with vector clone
+ DelimTokenTree (DelimTokenTree const &other)
+ : delim_type (other.delim_type), locus (other.locus)
+ {
+ token_trees.reserve (other.token_trees.size ());
+ for (const auto &e : other.token_trees)
+ token_trees.push_back (e->clone_token_tree ());
+ }
+
+ // overloaded assignment operator with vector clone
+ DelimTokenTree &operator= (DelimTokenTree const &other)
+ {
+ delim_type = other.delim_type;
+ locus = other.locus;
+
+ token_trees.reserve (other.token_trees.size ());
+ for (const auto &e : other.token_trees)
+ token_trees.push_back (e->clone_token_tree ());
+
+ return *this;
+ }
+
+ // move constructors
+ DelimTokenTree (DelimTokenTree &&other) = default;
+ DelimTokenTree &operator= (DelimTokenTree &&other) = default;
+
+ static DelimTokenTree create_empty () { return DelimTokenTree (PARENS); }
+
+ std::string as_string () const override;
+
+ void accept_vis (ASTVisitor &vis) override;
+
+ bool check_cfg_predicate (const Session &) const override
+ {
+ // this should never be called - should be converted first
+ return false;
+ }
+
+ AttrInput *parse_to_meta_item () const override;
+
+ std::vector<std::unique_ptr<Token> > to_token_stream () const override;
+
+ std::unique_ptr<DelimTokenTree> clone_delim_token_tree () const
+ {
+ return std::unique_ptr<DelimTokenTree> (clone_delim_tok_tree_impl ());
+ }
+};
+
+/* Forward decl - definition moved to rust-expr.h as it requires LiteralExpr to
+ * be defined */
+class AttrInputLiteral;
+
// Forward decl - defined in rust-macro.h
class MetaNameValueStr;
@@ -638,7 +635,10 @@ public:
/* HACK: used to simplify parsing - creates a copy of that type, or returns
* null */
- virtual std::unique_ptr<MetaNameValueStr> to_meta_name_value_str () const { return nullptr; }
+ virtual std::unique_ptr<MetaNameValueStr> to_meta_name_value_str () const
+ {
+ return nullptr;
+ }
// HACK: used to simplify parsing - same thing
virtual SimplePath to_path_item () const
@@ -646,7 +646,7 @@ public:
return SimplePath::create_empty ();
}
- virtual Attribute to_attribute() const { return Attribute::create_empty (); }
+ virtual Attribute to_attribute () const { return Attribute::create_empty (); }
virtual bool check_cfg_predicate (const Session &session) const = 0;
};
@@ -654,11 +654,11 @@ public:
// Container used to store MetaItems as AttrInput (bridge-ish kinda thing)
class AttrInputMetaItemContainer : public AttrInput
{
- std::vector<std::unique_ptr<MetaItemInner>> items;
+ std::vector<std::unique_ptr<MetaItemInner> > items;
public:
AttrInputMetaItemContainer (
- std::vector<std::unique_ptr<MetaItemInner>> items)
+ std::vector<std::unique_ptr<MetaItemInner> > items)
: items (std::move (items))
{}
@@ -683,6 +683,8 @@ public:
clone_attr_input_meta_item_container_impl ());
}
+ std::vector<Attribute> separate_cfg_attrs () const override;
+
protected:
// Use covariance to implement clone function as returning this type
AttrInputMetaItemContainer *clone_attr_input_impl () const override
@@ -764,6 +766,9 @@ public:
* methods. */
virtual Location get_locus_slow () const { return Location (); }
+ virtual void mark_for_strip () = 0;
+ virtual bool is_marked_for_strip () const = 0;
+
protected:
// Clone function implementation as pure virtual method
virtual Stmt *clone_stmt_impl () const = 0;
@@ -772,10 +777,6 @@ protected:
// Rust "item" AST node (declaration of top-level/module-level allowed stuff)
class Item : public Stmt
{
- std::vector<Attribute> outer_attrs;
-
- // TODO: should outer attrs be defined here or in each derived class?
-
public:
// Unique pointer custom clone function
std::unique_ptr<Item> clone_item () const
@@ -783,29 +784,22 @@ public:
return std::unique_ptr<Item> (clone_item_impl ());
}
- std::string as_string () const;
+ std::string as_string () const = 0;
/* Adds crate names to the vector passed by reference, if it can
- * (polymorphism). */
+ * (polymorphism). TODO: remove, unused. */
virtual void
add_crate_name (std::vector<std::string> &names ATTRIBUTE_UNUSED) const
{}
- virtual void accept_vis (ASTVisitor &vis ATTRIBUTE_UNUSED) {}
-
protected:
- // Constructor
- Item (std::vector<Attribute> outer_attribs = std::vector<Attribute> ())
- : outer_attrs (std::move (outer_attribs))
- {}
-
// Clone function implementation as pure virtual method
virtual Item *clone_item_impl () const = 0;
/* Save having to specify two clone methods in derived classes by making
* statement clone return item clone. Hopefully won't affect performance too
* much. */
- Item *clone_stmt_impl () const override { return clone_item_impl (); }
+ Item *clone_stmt_impl () const final override { return clone_item_impl (); }
};
// forward decl of ExprWithoutBlock
@@ -818,7 +812,9 @@ class Expr
std::vector<Attribute> outer_attrs;
public:
+ // TODO: this mutable getter seems really dodgy. Think up better way.
const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+ std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
// Unique pointer custom clone function
std::unique_ptr<Expr> clone_expr () const
@@ -849,6 +845,9 @@ public:
virtual void accept_vis (ASTVisitor &vis) = 0;
+ virtual void mark_for_strip () = 0;
+ virtual bool is_marked_for_strip () const = 0;
+
protected:
// Constructor
Expr (std::vector<Attribute> outer_attribs = std::vector<Attribute> ())
@@ -882,7 +881,7 @@ protected:
/* Save having to specify two clone methods in derived classes by making expr
* clone return exprwithoutblock clone. Hopefully won't affect performance too
* much. */
- ExprWithoutBlock *clone_expr_impl () const override
+ ExprWithoutBlock *clone_expr_impl () const final override
{
return clone_expr_without_block_impl ();
}
@@ -910,11 +909,10 @@ public:
*/
class IdentifierExpr : public ExprWithoutBlock
{
-public:
Identifier ident;
-
Location locus;
+public:
IdentifierExpr (Identifier ident, Location locus = Location (),
std::vector<Attribute> outer_attrs
= std::vector<Attribute> ())
@@ -927,6 +925,8 @@ public:
Location get_locus () const { return locus; }
Location get_locus_slow () const override { return get_locus (); }
+ Identifier get_ident () const { return ident; }
+
void accept_vis (ASTVisitor &vis) override;
// Clones this object.
@@ -935,6 +935,10 @@ public:
return std::unique_ptr<IdentifierExpr> (clone_identifier_expr_impl ());
}
+ // "Error state" if ident is empty, so base stripping on this.
+ void mark_for_strip () override { ident = {}; }
+ bool is_marked_for_strip () const override { return ident.empty (); }
+
protected:
// Clone method implementation
IdentifierExpr *clone_expr_without_block_impl () const override
@@ -946,9 +950,6 @@ protected:
{
return new IdentifierExpr (*this);
}
-
- IdentifierExpr (IdentifierExpr const &other) = default;
- IdentifierExpr &operator= (IdentifierExpr const &other) = default;
};
// Pattern base AST node
@@ -969,6 +970,14 @@ public:
virtual void accept_vis (ASTVisitor &vis) = 0;
+ // as only one kind of pattern can be stripped, have default of nothing
+ virtual void mark_for_strip () {}
+ virtual bool is_marked_for_strip () const { return false; }
+
+ /* HACK: slow way of getting location from base expression through virtual
+ * methods. */
+ virtual Location get_locus_slow () const = 0;
+
protected:
// Clone pattern implementation as pure virtual method
virtual Pattern *clone_pattern_impl () const = 0;
@@ -994,15 +1003,18 @@ public:
/* HACK: convert to trait bound. Virtual method overriden by classes that
* enable this. */
- virtual TraitBound *to_trait_bound (bool in_parens ATTRIBUTE_UNUSED) const
- {
- return nullptr;
- }
+ virtual TraitBound *to_trait_bound (bool) const { return nullptr; }
/* as pointer, shouldn't require definition beforehand, only forward
* declaration. */
virtual void accept_vis (ASTVisitor &vis) = 0;
+ // as only two kinds of types can be stripped, have default of nothing
+ virtual void mark_for_strip () {}
+ virtual bool is_marked_for_strip () const { return false; }
+
+ virtual Location get_locus_slow () const = 0;
+
protected:
// Clone function implementation as pure virtual method
virtual Type *clone_type_impl () const = 0;
@@ -1025,7 +1037,7 @@ protected:
/* Save having to specify two clone methods in derived classes by making type
* clone return typenobounds clone. Hopefully won't affect performance too
* much. */
- TypeNoBounds *clone_type_impl () const override
+ TypeNoBounds *clone_type_impl () const final override
{
return clone_type_no_bounds_impl ();
}
@@ -1082,7 +1094,7 @@ public:
{}
// Creates an "error" lifetime.
- static Lifetime error () { return Lifetime (NAMED, std::string ("")); }
+ static Lifetime error () { return Lifetime (NAMED, ""); }
// Returns true if the lifetime is in an error state.
bool is_error () const
@@ -1207,10 +1219,12 @@ class MacroItem : public Item
{
/*public:
std::string as_string() const;*/
+ // std::vector<Attribute> outer_attrs;
+
protected:
- MacroItem (std::vector<Attribute> outer_attribs)
- : Item (std::move (outer_attribs))
- {}
+ /*MacroItem (std::vector<Attribute> outer_attribs)
+ : outer_attrs (std::move (outer_attribs))
+ {}*/
};
// Item used in trait declarations - abstract base class
@@ -1223,21 +1237,12 @@ class TraitItem
// NOTE: all children should have outer attributes
protected:
- // Constructor
- /*TraitItem(std::vector<Attribute> outer_attrs = std::vector<Attribute>())
- : outer_attrs(std::move(outer_attrs)) {}*/
-
// Clone function implementation as pure virtual method
virtual TraitItem *clone_trait_item_impl () const = 0;
public:
virtual ~TraitItem () {}
- // Returns whether TraitItem has outer attributes.
- /*bool has_outer_attrs() const {
- return !outer_attrs.empty();
- }*/
-
// Unique pointer custom clone function
std::unique_ptr<TraitItem> clone_trait_item () const
{
@@ -1247,6 +1252,9 @@ public:
virtual std::string as_string () const = 0;
virtual void accept_vis (ASTVisitor &vis) = 0;
+
+ virtual void mark_for_strip () = 0;
+ virtual bool is_marked_for_strip () const = 0;
};
/* Abstract base class for items used within an inherent impl block (the impl
@@ -1269,6 +1277,9 @@ public:
virtual std::string as_string () const = 0;
virtual void accept_vis (ASTVisitor &vis) = 0;
+
+ virtual void mark_for_strip () = 0;
+ virtual bool is_marked_for_strip () const = 0;
};
// Abstract base class for items used in a trait impl
@@ -1289,6 +1300,33 @@ public:
virtual std::string as_string () const = 0;
virtual void accept_vis (ASTVisitor &vis) = 0;
+
+ virtual void mark_for_strip () = 0;
+ virtual bool is_marked_for_strip () const = 0;
+};
+
+// Abstract base class for an item used inside an extern block
+class ExternalItem
+{
+public:
+ virtual ~ExternalItem () {}
+
+ // Unique pointer custom clone function
+ std::unique_ptr<ExternalItem> clone_external_item () const
+ {
+ return std::unique_ptr<ExternalItem> (clone_external_item_impl ());
+ }
+
+ virtual std::string as_string () const = 0;
+
+ virtual void accept_vis (ASTVisitor &vis) = 0;
+
+ virtual void mark_for_strip () = 0;
+ virtual bool is_marked_for_strip () const = 0;
+
+protected:
+ // Clone function implementation as pure virtual method
+ virtual ExternalItem *clone_external_item_impl () const = 0;
};
/* A macro invocation item (or statement) AST node (i.e. semi-coloned macro
@@ -1296,51 +1334,32 @@ public:
class MacroInvocationSemi : public MacroItem,
public TraitItem,
public InherentImplItem,
- public TraitImplItem
+ public TraitImplItem,
+ public ExternalItem
{
+ std::vector<Attribute> outer_attrs;
SimplePath path;
// all delim types except curly must have invocation end with a semicolon
DelimType delim_type;
- std::vector<std::unique_ptr<TokenTree>> token_trees;
+ std::vector<std::unique_ptr<TokenTree> > token_trees;
Location locus;
public:
std::string as_string () const override;
MacroInvocationSemi (SimplePath macro_path, DelimType delim_type,
- std::vector<std::unique_ptr<TokenTree>> token_trees,
+ std::vector<std::unique_ptr<TokenTree> > token_trees,
std::vector<Attribute> outer_attribs, Location locus)
- : MacroItem (std::move (outer_attribs)), path (std::move (macro_path)),
+ : outer_attrs (std::move (outer_attribs)), path (std::move (macro_path)),
delim_type (delim_type), token_trees (std::move (token_trees)),
locus (locus)
{}
- /* TODO: possible issue with Item and TraitItem hierarchies both having outer
- * attributes
- * - storage inefficiency at least.
- * Best current idea is to make Item preferred and have TraitItem get virtual
- * functions for attributes or something. Or just redo the "composition"
- * approach, but then this prevents polymorphism and would entail redoing
- * quite a bit of the parser. */
-
- // Move constructors
- MacroInvocationSemi (MacroInvocationSemi &&other) = default;
- MacroInvocationSemi &operator= (MacroInvocationSemi &&other) = default;
-
- void accept_vis (ASTVisitor &vis) override;
-
- // Clones this macro invocation semi.
- std::unique_ptr<MacroInvocationSemi> clone_macro_invocation_semi () const
- {
- return std::unique_ptr<MacroInvocationSemi> (
- clone_macro_invocation_semi_impl ());
- }
-protected:
// Copy constructor with vector clone
MacroInvocationSemi (MacroInvocationSemi const &other)
: MacroItem (other), TraitItem (other), InherentImplItem (other),
- TraitImplItem (other), path (other.path), delim_type (other.delim_type),
- locus (other.locus)
+ TraitImplItem (other), outer_attrs (other.outer_attrs), path (other.path),
+ delim_type (other.delim_type), locus (other.locus)
{
token_trees.reserve (other.token_trees.size ());
for (const auto &e : other.token_trees)
@@ -1354,6 +1373,7 @@ protected:
TraitItem::operator= (other);
InherentImplItem::operator= (other);
TraitImplItem::operator= (other);
+ outer_attrs = other.outer_attrs;
path = other.path;
delim_type = other.delim_type;
locus = other.locus;
@@ -1365,6 +1385,28 @@ protected:
return *this;
}
+ // Move constructors
+ MacroInvocationSemi (MacroInvocationSemi &&other) = default;
+ MacroInvocationSemi &operator= (MacroInvocationSemi &&other) = default;
+
+ void accept_vis (ASTVisitor &vis) override;
+
+ // Clones this macro invocation semi.
+ std::unique_ptr<MacroInvocationSemi> clone_macro_invocation_semi () const
+ {
+ return std::unique_ptr<MacroInvocationSemi> (
+ clone_macro_invocation_semi_impl ());
+ }
+
+ // Invalid if path is empty, so base stripping on that.
+ void mark_for_strip () override { path = SimplePath::create_empty (); }
+ bool is_marked_for_strip () const override { return path.is_empty (); }
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+ std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
+
+protected:
MacroInvocationSemi *clone_macro_invocation_semi_impl () const
{
return new MacroInvocationSemi (*this);
@@ -1391,19 +1433,19 @@ protected:
return clone_macro_invocation_semi_impl ();
}
- // FIXME: remove if item impl virtual override works properly
- // Use covariance to implement clone function as returning this object rather
- // than base
- /*MacroInvocationSemi* clone_statement_impl() const override {
- return clone_macro_invocation_semi_impl ();
- }*/
-
/* Use covariance to implement clone function as returning this object rather
* than base */
MacroInvocationSemi *clone_trait_item_impl () const override
{
return clone_macro_invocation_semi_impl ();
}
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ MacroInvocationSemi *clone_external_item_impl () const override
+ {
+ return clone_macro_invocation_semi_impl ();
+ }
};
// A crate AST object - holds all the data for a single compilation unit
@@ -1416,11 +1458,11 @@ struct Crate
// dodgy spacing required here
/* TODO: is it better to have a vector of items here or a module (implicit
* top-level one)? */
- std::vector<std::unique_ptr<Item>> items;
+ std::vector<std::unique_ptr<Item> > items;
public:
// Constructor
- Crate (std::vector<std::unique_ptr<Item>> items,
+ Crate (std::vector<std::unique_ptr<Item> > items,
std::vector<Attribute> inner_attrs, bool has_utf8bom = false,
bool has_shebang = false)
: has_utf8bom (has_utf8bom), has_shebang (has_shebang),
@@ -1459,6 +1501,17 @@ public:
// Get crate representation as string (e.g. for debugging).
std::string as_string () const;
+
+ // Delete all crate information, e.g. if fails cfg.
+ void strip_crate ()
+ {
+ inner_attrs.clear ();
+ inner_attrs.shrink_to_fit ();
+
+ items.clear ();
+ items.shrink_to_fit ();
+ // TODO: is this the best way to do this?
+ }
};
// Base path expression AST node - abstract
diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h
index f587c00..f86aa54 100644
--- a/gcc/rust/ast/rust-expr.h
+++ b/gcc/rust/ast/rust-expr.h
@@ -23,7 +23,7 @@ protected:
virtual ExprWithBlock *clone_expr_with_block_impl () const = 0;
// prevent having to define multiple clone expressions
- ExprWithBlock *clone_expr_impl () const override
+ ExprWithBlock *clone_expr_impl () const final override
{
return clone_expr_with_block_impl ();
}
@@ -41,10 +41,10 @@ public:
// Literals? Or literal base?
class LiteralExpr : public ExprWithoutBlock
{
-public:
Literal literal;
Location locus;
+public:
std::string as_string () const override { return literal.as_string (); }
Literal::LitType get_lit_type () const { return literal.get_lit_type (); }
@@ -71,21 +71,20 @@ public:
Location get_locus () const { return locus; }
Location get_locus_slow () const override { return get_locus (); }
+ Literal get_literal () const { return literal; }
+
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- LiteralExpr *clone_expr_impl () const override
- {
- return new LiteralExpr (*this);
- }
+ // Invalid if literal is in error state, so base stripping on that.
+ void mark_for_strip () override { literal = Literal::create_error (); }
+ bool is_marked_for_strip () const override { return literal.is_error (); }
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
LiteralExpr *clone_expr_without_block_impl () const override
{
- return new LiteralExpr (*this);
+ return clone_literal_expr_impl ();
}
/* not virtual as currently no subclasses of LiteralExpr, but could be in
@@ -120,11 +119,7 @@ public:
/* this can never be a cfg predicate - cfg and cfg_attr require a token-tree
* cfg */
- bool
- check_cfg_predicate (const Session &session ATTRIBUTE_UNUSED) const override
- {
- return false;
- }
+ bool check_cfg_predicate (const Session &) const override { return false; }
protected:
/* Use covariance to implement clone function as returning this object rather
@@ -212,18 +207,26 @@ protected:
// Copy constructor (only for initialisation of expr purposes)
OperatorExpr (OperatorExpr const &other)
- : ExprWithoutBlock (other), locus (other.locus),
- main_or_left_expr (other.main_or_left_expr->clone_expr ())
- {}
+ : ExprWithoutBlock (other), locus (other.locus)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.main_or_left_expr != nullptr)
+ main_or_left_expr = other.main_or_left_expr->clone_expr ();
+ }
// Overload assignment operator to deep copy expr
OperatorExpr &operator= (OperatorExpr const &other)
{
ExprWithoutBlock::operator= (other);
- main_or_left_expr = other.main_or_left_expr->clone_expr ();
locus = other.locus;
// outer_attrs = other.outer_attrs;
+ // guard to prevent null dereference (only required if error state)
+ if (other.main_or_left_expr != nullptr)
+ main_or_left_expr = other.main_or_left_expr->clone_expr ();
+ else
+ main_or_left_expr = nullptr;
+
return *this;
}
@@ -234,6 +237,13 @@ protected:
public:
Location get_locus () const { return locus; }
Location get_locus_slow () const override { return get_locus (); }
+
+ // Invalid if expr is null, so base stripping on that.
+ void mark_for_strip () override { main_or_left_expr = nullptr; }
+ bool is_marked_for_strip () const override
+ {
+ return main_or_left_expr == nullptr;
+ }
};
/* Unary prefix & or &mut (or && and &&mut) borrow operator. Cannot be
@@ -256,14 +266,14 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- BorrowExpr *clone_expr_impl () const override
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_borrowed_expr ()
{
- return new BorrowExpr (*this);
+ rust_assert (main_or_left_expr != nullptr);
+ return main_or_left_expr;
}
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
BorrowExpr *clone_expr_without_block_impl () const override
@@ -286,14 +296,14 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- DereferenceExpr *clone_expr_impl () const override
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_dereferenced_expr ()
{
- return new DereferenceExpr (*this);
+ rust_assert (main_or_left_expr != nullptr);
+ return main_or_left_expr;
}
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
DereferenceExpr *clone_expr_without_block_impl () const override
@@ -317,14 +327,14 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- ErrorPropagationExpr *clone_expr_impl () const override
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_propagating_expr ()
{
- return new ErrorPropagationExpr (*this);
+ rust_assert (main_or_left_expr != nullptr);
+ return main_or_left_expr;
}
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
ErrorPropagationExpr *clone_expr_without_block_impl () const override
@@ -343,6 +353,7 @@ public:
NOT
};
+private:
/* Note: overload negation via std::ops::Neg and not via std::ops::Not
* Negation only works for signed integer and floating-point types, NOT only
* works for boolean and integer types (via bitwise NOT) */
@@ -363,16 +374,14 @@ public:
void accept_vis (ASTVisitor &vis) override;
- Expr *get_expr () { return main_or_left_expr.get (); }
-
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- NegationExpr *clone_expr_impl () const override
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_negated_expr ()
{
- return new NegationExpr (*this);
+ rust_assert (main_or_left_expr != nullptr);
+ return main_or_left_expr;
}
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
NegationExpr *clone_expr_without_block_impl () const override
@@ -399,6 +408,7 @@ public:
RIGHT_SHIFT // std::ops::Shr
};
+private:
// Note: overloading trait specified in comments
ExprType expr_type;
@@ -442,7 +452,19 @@ public:
void accept_vis (ASTVisitor &vis) override;
- Expr *get_lhs () { return main_or_left_expr.get (); }
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_left_expr ()
+ {
+ rust_assert (main_or_left_expr != nullptr);
+ return main_or_left_expr;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_right_expr ()
+ {
+ rust_assert (right_expr != nullptr);
+ return right_expr;
+ }
void visit_lhs (ASTVisitor &vis) { main_or_left_expr->accept_vis (vis); }
void visit_rhs (ASTVisitor &vis) { right_expr->accept_vis (vis); }
@@ -450,13 +472,6 @@ public:
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
- ArithmeticOrLogicalExpr *clone_expr_impl () const override
- {
- return new ArithmeticOrLogicalExpr (*this);
- }
-
- /* Use covariance to implement clone function as returning this object rather
- * than base */
ArithmeticOrLogicalExpr *clone_expr_without_block_impl () const override
{
return new ArithmeticOrLogicalExpr (*this);
@@ -477,6 +492,7 @@ public:
LESS_OR_EQUAL // std::cmp::PartialEq::le
};
+private:
// Note: overloading trait specified in comments
ExprType expr_type;
@@ -520,18 +536,23 @@ public:
void accept_vis (ASTVisitor &vis) override;
- Expr *get_lhs () { return main_or_left_expr.get (); }
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_left_expr ()
+ {
+ rust_assert (main_or_left_expr != nullptr);
+ return main_or_left_expr;
+ }
- /* TODO: implement via a function call to std::cmp::PartialEq::eq(&op1, &op2)
- * maybe? */
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- ComparisonExpr *clone_expr_impl () const override
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_right_expr ()
{
- return new ComparisonExpr (*this);
+ rust_assert (right_expr != nullptr);
+ return right_expr;
}
+ /* TODO: implement via a function call to std::cmp::PartialEq::eq(&op1, &op2)
+ * maybe? */
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
ComparisonExpr *clone_expr_without_block_impl () const override
@@ -550,6 +571,7 @@ public:
LOGICAL_AND
};
+private:
ExprType expr_type;
std::unique_ptr<Expr> right_expr;
@@ -592,16 +614,21 @@ public:
void accept_vis (ASTVisitor &vis) override;
- Expr *get_lhs () { return main_or_left_expr.get (); }
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_left_expr ()
+ {
+ rust_assert (main_or_left_expr != nullptr);
+ return main_or_left_expr;
+ }
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- LazyBooleanExpr *clone_expr_impl () const override
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_right_expr ()
{
- return new LazyBooleanExpr (*this);
+ rust_assert (right_expr != nullptr);
+ return right_expr;
}
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
LazyBooleanExpr *clone_expr_without_block_impl () const override
@@ -643,20 +670,27 @@ public:
return *this;
}
- // move constructors as not supported in c++03
+ // move constructors
TypeCastExpr (TypeCastExpr &&other) = default;
TypeCastExpr &operator= (TypeCastExpr &&other) = default;
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- TypeCastExpr *clone_expr_impl () const override
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_casted_expr ()
{
- return new TypeCastExpr (*this);
+ rust_assert (main_or_left_expr != nullptr);
+ return main_or_left_expr;
}
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<TypeNoBounds> &get_type_to_cast_to ()
+ {
+ rust_assert (type_to_convert_to != nullptr);
+ return type_to_convert_to;
+ }
+
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
TypeCastExpr *clone_expr_without_block_impl () const override
@@ -668,9 +702,9 @@ protected:
// Binary assignment expression.
class AssignmentExpr : public OperatorExpr
{
-public:
std::unique_ptr<Expr> right_expr;
+public:
std::string as_string () const override;
// Call OperatorExpr constructor to initialise left_expr
@@ -707,16 +741,21 @@ public:
void visit_lhs (ASTVisitor &vis) { main_or_left_expr->accept_vis (vis); }
void visit_rhs (ASTVisitor &vis) { right_expr->accept_vis (vis); }
- Expr *get_lhs () { return main_or_left_expr.get (); }
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_left_expr ()
+ {
+ rust_assert (main_or_left_expr != nullptr);
+ return main_or_left_expr;
+ }
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- AssignmentExpr *clone_expr_impl () const override
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_right_expr ()
{
- return new AssignmentExpr (*this);
+ rust_assert (right_expr != nullptr);
+ return right_expr;
}
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
AssignmentExpr *clone_expr_without_block_impl () const override
@@ -788,14 +827,21 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- CompoundAssignmentExpr *clone_expr_impl () const override
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_left_expr ()
{
- return new CompoundAssignmentExpr (*this);
+ rust_assert (main_or_left_expr != nullptr);
+ return main_or_left_expr;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_right_expr ()
+ {
+ rust_assert (right_expr != nullptr);
+ return right_expr;
}
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
CompoundAssignmentExpr *clone_expr_without_block_impl () const override
@@ -815,7 +861,8 @@ class GroupedExpr : public ExprWithoutBlock
public:
std::string as_string () const override;
- std::vector<Attribute> get_inner_attrs () const { return inner_attrs; }
+ const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
+ std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
GroupedExpr (std::unique_ptr<Expr> parenthesised_expr,
std::vector<Attribute> inner_attribs,
@@ -828,18 +875,27 @@ public:
// Copy constructor includes clone for expr_in_parens
GroupedExpr (GroupedExpr const &other)
: ExprWithoutBlock (other), inner_attrs (other.inner_attrs),
- expr_in_parens (other.expr_in_parens->clone_expr ()), locus (other.locus)
- {}
+ locus (other.locus)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.expr_in_parens != nullptr)
+ expr_in_parens = other.expr_in_parens->clone_expr ();
+ }
// Overloaded assignment operator to clone expr_in_parens
GroupedExpr &operator= (GroupedExpr const &other)
{
ExprWithoutBlock::operator= (other);
inner_attrs = other.inner_attrs;
- expr_in_parens = other.expr_in_parens->clone_expr ();
locus = other.locus;
// outer_attrs = other.outer_attrs;
+ // guard to prevent null dereference (only required if error state)
+ if (other.expr_in_parens != nullptr)
+ expr_in_parens = other.expr_in_parens->clone_expr ();
+ else
+ expr_in_parens = nullptr;
+
return *this;
}
@@ -852,14 +908,21 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- GroupedExpr *clone_expr_impl () const override
+ // Invalid if inner expr is null, so base stripping on that.
+ void mark_for_strip () override { expr_in_parens = nullptr; }
+ bool is_marked_for_strip () const override
{
- return new GroupedExpr (*this);
+ return expr_in_parens == nullptr;
}
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_expr_in_parens ()
+ {
+ rust_assert (expr_in_parens != nullptr);
+ return expr_in_parens;
+ }
+
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
GroupedExpr *clone_expr_without_block_impl () const override
@@ -928,6 +991,13 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ const std::vector<std::unique_ptr<Expr> > &get_values () const
+ {
+ return values;
+ }
+ std::vector<std::unique_ptr<Expr> > &get_values () { return values; }
+
size_t get_num_values () const { return values.size (); }
void iterate (std::function<bool (Expr *)> cb)
@@ -985,6 +1055,20 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_elem_to_copy ()
+ {
+ rust_assert (elem_to_copy != nullptr);
+ return elem_to_copy;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_num_copies ()
+ {
+ rust_assert (num_copies != nullptr);
+ return num_copies;
+ }
+
protected:
ArrayElemsCopied *clone_array_elems_impl () const override
{
@@ -1000,6 +1084,9 @@ class ArrayExpr : public ExprWithoutBlock
Location locus;
+ // TODO: find another way to store this to save memory?
+ bool marked_for_strip = false;
+
// this is a reference to what the inferred type is based on
// this init expression
Type *inferredType;
@@ -1007,7 +1094,8 @@ class ArrayExpr : public ExprWithoutBlock
public:
std::string as_string () const override;
- std::vector<Attribute> get_inner_attrs () const { return inner_attrs; }
+ const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
+ std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
// Returns whether array expr has array elems or if it is just empty.
bool has_array_elems () const { return internal_elements != nullptr; }
@@ -1024,7 +1112,7 @@ public:
// Copy constructor requires cloning ArrayElems for polymorphism to hold
ArrayExpr (ArrayExpr const &other)
: ExprWithoutBlock (other), inner_attrs (other.inner_attrs),
- locus (other.locus)
+ locus (other.locus), marked_for_strip (other.marked_for_strip)
{
if (other.has_array_elems ())
internal_elements = other.internal_elements->clone_array_elems ();
@@ -1035,11 +1123,15 @@ public:
{
ExprWithoutBlock::operator= (other);
inner_attrs = other.inner_attrs;
- if (other.has_array_elems ())
- internal_elements = other.internal_elements->clone_array_elems ();
locus = other.locus;
+ marked_for_strip = other.marked_for_strip;
// outer_attrs = other.outer_attrs;
+ if (other.has_array_elems ())
+ internal_elements = other.internal_elements->clone_array_elems ();
+ else
+ internal_elements = nullptr;
+
return *this;
}
@@ -1052,7 +1144,16 @@ public:
void accept_vis (ASTVisitor &vis) override;
- ArrayElems *get_internal_elements () { return internal_elements.get (); };
+ // Can't think of any invalid invariants, so store boolean.
+ void mark_for_strip () override { marked_for_strip = true; }
+ bool is_marked_for_strip () const override { return marked_for_strip; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<ArrayElems> &get_array_elems ()
+ {
+ rust_assert (internal_elements != nullptr);
+ return internal_elements;
+ }
Type *get_inferred_type () { return inferredType; }
void set_inferred_type (Type *type) { inferredType = type; }
@@ -1060,10 +1161,6 @@ public:
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
- ArrayExpr *clone_expr_impl () const override { return new ArrayExpr (*this); }
-
- /* Use covariance to implement clone function as returning this object rather
- * than base */
ArrayExpr *clone_expr_without_block_impl () const override
{
return new ArrayExpr (*this);
@@ -1095,19 +1192,32 @@ public:
// Copy constructor requires special cloning due to unique_ptr
ArrayIndexExpr (ArrayIndexExpr const &other)
- : ExprWithoutBlock (other), array_expr (other.array_expr->clone_expr ()),
- index_expr (other.index_expr->clone_expr ()), locus (other.locus)
- {}
+ : ExprWithoutBlock (other), locus (other.locus)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.array_expr != nullptr)
+ array_expr = other.array_expr->clone_expr ();
+ if (other.index_expr != nullptr)
+ index_expr = other.index_expr->clone_expr ();
+ }
// Overload assignment operator to clone unique_ptrs
ArrayIndexExpr &operator= (ArrayIndexExpr const &other)
{
ExprWithoutBlock::operator= (other);
- array_expr = other.array_expr->clone_expr ();
- index_expr = other.index_expr->clone_expr ();
// outer_attrs = other.outer_attrs;
locus = other.locus;
+ // guard to prevent null dereference (only required if error state)
+ if (other.array_expr != nullptr)
+ array_expr = other.array_expr->clone_expr ();
+ else
+ array_expr = nullptr;
+ if (other.index_expr != nullptr)
+ index_expr = other.index_expr->clone_expr ();
+ else
+ index_expr = nullptr;
+
return *this;
}
@@ -1120,17 +1230,32 @@ public:
void accept_vis (ASTVisitor &vis) override;
- Expr *get_array_expr () { return array_expr.get (); }
- Expr *get_index_expr () { return index_expr.get (); }
+ // Invalid if either expr is null, so base stripping on that.
+ void mark_for_strip () override
+ {
+ array_expr = nullptr;
+ index_expr = nullptr;
+ }
+ bool is_marked_for_strip () const override
+ {
+ return array_expr == nullptr && index_expr == nullptr;
+ }
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- ArrayIndexExpr *clone_expr_impl () const override
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_array_expr ()
{
- return new ArrayIndexExpr (*this);
+ rust_assert (array_expr != nullptr);
+ return array_expr;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_index_expr ()
+ {
+ rust_assert (index_expr != nullptr);
+ return index_expr;
}
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
ArrayIndexExpr *clone_expr_without_block_impl () const override
@@ -1149,10 +1274,14 @@ class TupleExpr : public ExprWithoutBlock
Location locus;
+ // TODO: find another way to store this to save memory?
+ bool marked_for_strip = false;
+
public:
std::string as_string () const override;
- std::vector<Attribute> get_inner_attrs () const { return inner_attrs; }
+ const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
+ std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
TupleExpr (std::vector<std::unique_ptr<Expr> > tuple_elements,
std::vector<Attribute> inner_attribs,
@@ -1165,7 +1294,7 @@ public:
// copy constructor with vector clone
TupleExpr (TupleExpr const &other)
: ExprWithoutBlock (other), inner_attrs (other.inner_attrs),
- locus (other.locus)
+ locus (other.locus), marked_for_strip (other.marked_for_strip)
{
tuple_elems.reserve (other.tuple_elems.size ());
for (const auto &e : other.tuple_elems)
@@ -1178,6 +1307,7 @@ public:
ExprWithoutBlock::operator= (other);
inner_attrs = other.inner_attrs;
locus = other.locus;
+ marked_for_strip = other.marked_for_strip;
tuple_elems.reserve (other.tuple_elems.size ());
for (const auto &e : other.tuple_elems)
@@ -1198,11 +1328,21 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- TupleExpr *clone_expr_impl () const override { return new TupleExpr (*this); }
+ // Can't think of any invalid invariants, so store boolean.
+ void mark_for_strip () override { marked_for_strip = true; }
+ bool is_marked_for_strip () const override { return marked_for_strip; }
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ const std::vector<std::unique_ptr<Expr> > &get_tuple_elems () const
+ {
+ return tuple_elems;
+ }
+ std::vector<std::unique_ptr<Expr> > &get_tuple_elems ()
+ {
+ return tuple_elems;
+ }
+
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
TupleExpr *clone_expr_without_block_impl () const override
@@ -1236,19 +1376,28 @@ public:
// Copy constructor requires a clone for tuple_expr
TupleIndexExpr (TupleIndexExpr const &other)
- : ExprWithoutBlock (other), tuple_expr (other.tuple_expr->clone_expr ()),
- tuple_index (other.tuple_index), locus (other.locus)
- {}
+ : ExprWithoutBlock (other), tuple_index (other.tuple_index),
+ locus (other.locus)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.tuple_expr != nullptr)
+ tuple_expr = other.tuple_expr->clone_expr ();
+ }
// Overload assignment operator in order to clone
TupleIndexExpr &operator= (TupleIndexExpr const &other)
{
ExprWithoutBlock::operator= (other);
- tuple_expr = other.tuple_expr->clone_expr ();
tuple_index = other.tuple_index;
locus = other.locus;
// outer_attrs = other.outer_attrs;
+ // guard to prevent null dereference (only required if error state)
+ if (other.tuple_expr != nullptr)
+ tuple_expr = other.tuple_expr->clone_expr ();
+ else
+ tuple_expr = nullptr;
+
return *this;
}
@@ -1261,14 +1410,18 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- TupleIndexExpr *clone_expr_impl () const override
+ // Invalid if tuple expr is null, so base stripping on that.
+ void mark_for_strip () override { tuple_expr = nullptr; }
+ bool is_marked_for_strip () const override { return tuple_expr == nullptr; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_tuple_expr ()
{
- return new TupleIndexExpr (*this);
+ rust_assert (tuple_expr != nullptr);
+ return tuple_expr;
}
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
TupleIndexExpr *clone_expr_without_block_impl () const override
@@ -1292,8 +1445,16 @@ protected:
public:
const PathInExpression &get_struct_name () const { return struct_name; }
+ PathInExpression &get_struct_name () { return struct_name; }
std::string as_string () const override;
+
+ // Invalid if path is empty, so base stripping on that.
+ void mark_for_strip () override
+ {
+ struct_name = PathInExpression::create_error ();
+ }
+ bool is_marked_for_strip () const override { return struct_name.is_error (); }
};
// Actual AST node of the struct creator (with no fields). Not abstract!
@@ -1306,7 +1467,8 @@ class StructExprStruct : public StructExpr
public:
std::string as_string () const override;
- std::vector<Attribute> get_inner_attrs () const { return inner_attrs; }
+ const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
+ std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
// Constructor has to call protected constructor of base class
StructExprStruct (PathInExpression struct_path,
@@ -1324,13 +1486,6 @@ public:
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
- StructExprStruct *clone_expr_impl () const override
- {
- return new StructExprStruct (*this);
- }
-
- /* Use covariance to implement clone function as returning this object rather
- * than base */
StructExprStruct *clone_expr_without_block_impl () const override
{
return new StructExprStruct (*this);
@@ -1341,9 +1496,10 @@ protected:
* struct */
struct StructBase
{
-public:
+private:
std::unique_ptr<Expr> base_struct;
+public:
// TODO: should this store location data?
StructBase (std::unique_ptr<Expr> base_struct_ptr)
: base_struct (std::move (base_struct_ptr))
@@ -1355,7 +1511,7 @@ public:
/* HACK: gets around base_struct pointer being null (e.g. if no struct base
* exists) */
if (other.base_struct != nullptr)
- other.base_struct->clone_expr ();
+ base_struct = other.base_struct->clone_expr ();
}
// Destructor
@@ -1364,7 +1520,11 @@ public:
// Overload assignment operator to clone base_struct
StructBase &operator= (StructBase const &other)
{
- base_struct = other.base_struct->clone_expr ();
+ // prevent null pointer dereference
+ if (other.base_struct != nullptr)
+ base_struct = other.base_struct->clone_expr ();
+ else
+ base_struct = nullptr;
return *this;
}
@@ -1380,6 +1540,13 @@ public:
bool is_invalid () const { return base_struct == nullptr; }
std::string as_string () const;
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_base_struct ()
+ {
+ rust_assert (base_struct != nullptr);
+ return base_struct;
+ }
};
/* Base AST node for a single struct expression field (in struct instance
@@ -1399,6 +1566,8 @@ public:
virtual void accept_vis (ASTVisitor &vis) = 0;
+ virtual Location get_locus_slow () const = 0;
+
protected:
// pure virtual clone implementation
virtual StructExprField *clone_struct_expr_field_impl () const = 0;
@@ -1407,17 +1576,19 @@ protected:
// Identifier-only variant of StructExprField AST node
class StructExprFieldIdentifier : public StructExprField
{
-public:
Identifier field_name;
+ Location locus;
- // TODO: should this store location data?
-
- StructExprFieldIdentifier (Identifier field_identifier)
- : field_name (std::move (field_identifier))
+public:
+ StructExprFieldIdentifier (Identifier field_identifier, Location locus)
+ : field_name (std::move (field_identifier)), locus (locus)
{}
std::string as_string () const override { return field_name; }
+ Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
+
void accept_vis (ASTVisitor &vis) override;
protected:
@@ -1433,7 +1604,6 @@ protected:
* abstract */
class StructExprFieldWithVal : public StructExprField
{
-public:
std::unique_ptr<Expr> value;
protected:
@@ -1460,26 +1630,37 @@ protected:
public:
std::string as_string () const override;
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_value ()
+ {
+ rust_assert (value != nullptr);
+ return value;
+ }
};
// Identifier and value variant of StructExprField AST node
class StructExprFieldIdentifierValue : public StructExprFieldWithVal
{
-public:
Identifier field_name;
+ Location locus;
- // TODO: should this store location data?
-
+public:
StructExprFieldIdentifierValue (Identifier field_identifier,
- std::unique_ptr<Expr> field_value)
+ std::unique_ptr<Expr> field_value, Location locus)
: StructExprFieldWithVal (std::move (field_value)),
- field_name (std::move (field_identifier))
+ field_name (std::move (field_identifier)), locus (locus)
{}
std::string as_string () const override;
void accept_vis (ASTVisitor &vis) override;
+ std::string get_field_name () const { return field_name; }
+
+ Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1492,20 +1673,24 @@ protected:
// Tuple index and value variant of StructExprField AST node
class StructExprFieldIndexValue : public StructExprFieldWithVal
{
-public:
TupleIndex index;
+ Location locus;
- // TODO: should this store location data?
-
+public:
StructExprFieldIndexValue (TupleIndex tuple_index,
- std::unique_ptr<Expr> field_value)
- : StructExprFieldWithVal (std::move (field_value)), index (tuple_index)
+ std::unique_ptr<Expr> field_value, Location locus)
+ : StructExprFieldWithVal (std::move (field_value)), index (tuple_index), locus (locus)
{}
std::string as_string () const override;
void accept_vis (ASTVisitor &vis) override;
+ TupleIndex get_index () const { return index; }
+
+ Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1518,25 +1703,17 @@ protected:
// AST node of a struct creator with fields
class StructExprStructFields : public StructExprStruct
{
-public:
// std::vector<StructExprField> fields;
std::vector<std::unique_ptr<StructExprField> > fields;
// bool has_struct_base;
StructBase struct_base;
+public:
std::string as_string () const override;
bool has_struct_base () const { return !struct_base.is_invalid (); }
- /*inline std::vector<std::unique_ptr<StructExprField>> get_fields()
- const { return fields;
- }*/
-
- /*inline StructBase get_struct_base() const {
- return has_struct_base ? struct_base : StructBase::error();
- }*/
-
// Constructor for StructExprStructFields when no struct base is used
StructExprStructFields (
PathInExpression struct_path,
@@ -1577,14 +1754,20 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- StructExprStructFields *clone_expr_impl () const override
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<std::unique_ptr<StructExprField> > &get_fields ()
{
- return new StructExprStructFields (*this);
+ return fields;
+ }
+ const std::vector<std::unique_ptr<StructExprField> > &get_fields () const
+ {
+ return fields;
}
+ StructBase &get_struct_base () { return struct_base; }
+ const StructBase &get_struct_base () const { return struct_base; }
+
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
StructExprStructFields *clone_expr_without_block_impl () const override
@@ -1594,6 +1777,8 @@ protected:
};
// AST node of the functional update struct creator
+/* TODO: remove and replace with StructExprStructFields, except with empty
+ * vector of fields? */
class StructExprStructBase : public StructExprStruct
{
StructBase struct_base;
@@ -1601,10 +1786,6 @@ class StructExprStructBase : public StructExprStruct
public:
std::string as_string () const override;
- /*inline StructBase get_struct_base() const {
- return struct_base;
- }*/
-
StructExprStructBase (PathInExpression struct_path, StructBase base_struct,
std::vector<Attribute> inner_attribs,
std::vector<Attribute> outer_attribs, Location locus)
@@ -1615,14 +1796,10 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- StructExprStructBase *clone_expr_impl () const override
- {
- return new StructExprStructBase (*this);
- }
+ StructBase &get_struct_base () { return struct_base; }
+ const StructBase &get_struct_base () const { return struct_base; }
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
StructExprStructBase *clone_expr_without_block_impl () const override
@@ -1643,10 +1820,7 @@ public:
std::string as_string () const override;
const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
-
- /*inline std::vector<std::unique_ptr<Expr>> get_exprs() const {
- return exprs;
- }*/
+ std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
StructExprTuple (PathInExpression struct_path,
std::vector<std::unique_ptr<Expr> > tuple_exprs,
@@ -1689,14 +1863,13 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- StructExprTuple *clone_expr_impl () const override
+ const std::vector<std::unique_ptr<Expr> > &get_elems () const
{
- return new StructExprTuple (*this);
+ return exprs;
}
+ std::vector<std::unique_ptr<Expr> > &get_elems () { return exprs; }
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
StructExprTuple *clone_expr_without_block_impl () const override
@@ -1714,7 +1887,6 @@ public:
std::string as_string () const override
{
return get_struct_name ().as_string ();
- // return struct_name.as_string();
}
StructExprUnit (PathInExpression struct_path,
@@ -1731,13 +1903,6 @@ public:
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
- StructExprUnit *clone_expr_impl () const override
- {
- return new StructExprUnit (*this);
- }
-
- /* Use covariance to implement clone function as returning this object rather
- * than base */
StructExprUnit *clone_expr_without_block_impl () const override
{
return new StructExprUnit (*this);
@@ -1759,8 +1924,21 @@ protected:
{}
public:
- // TODO: maybe remove and have string version gotten here directly
- PathInExpression get_enum_variant_path () const { return enum_variant_path; }
+ const PathInExpression &get_enum_variant_path () const
+ {
+ return enum_variant_path;
+ }
+ PathInExpression &get_enum_variant_path () { return enum_variant_path; }
+
+ // Invalid if path is in error state, so base stripping on that.
+ void mark_for_strip () override
+ {
+ enum_variant_path = PathInExpression::create_error ();
+ }
+ bool is_marked_for_strip () const override
+ {
+ return enum_variant_path.is_error ();
+ }
};
/* Base AST node for a single enum expression field (in enum instance creation)
@@ -1776,8 +1954,12 @@ public:
return std::unique_ptr<EnumExprField> (clone_enum_expr_field_impl ());
}
+ virtual std::string as_string () const = 0;
+
virtual void accept_vis (ASTVisitor &vis) = 0;
+ virtual Location get_locus_slow () const = 0;
+
protected:
// Clone function implementation as pure virtual method
virtual EnumExprField *clone_enum_expr_field_impl () const = 0;
@@ -1787,16 +1969,20 @@ protected:
class EnumExprFieldIdentifier : public EnumExprField
{
Identifier field_name;
-
- // TODO: should this store location data?
+ Location locus;
public:
- EnumExprFieldIdentifier (Identifier field_identifier)
- : field_name (std::move (field_identifier))
+ EnumExprFieldIdentifier (Identifier field_identifier, Location locus)
+ : field_name (std::move (field_identifier)), locus (locus)
{}
void accept_vis (ASTVisitor &vis) override;
+ std::string as_string () const override { return field_name; }
+
+ Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1812,8 +1998,6 @@ class EnumExprFieldWithVal : public EnumExprField
{
std::unique_ptr<Expr> value;
- // TODO: should this store location data?
-
protected:
EnumExprFieldWithVal (std::unique_ptr<Expr> field_value)
: value (std::move (field_value))
@@ -1835,27 +2019,38 @@ protected:
// move constructors
EnumExprFieldWithVal (EnumExprFieldWithVal &&other) = default;
EnumExprFieldWithVal &operator= (EnumExprFieldWithVal &&other) = default;
+
+public:
+ std::string as_string () const override;
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_value ()
+ {
+ rust_assert (value != nullptr);
+ return value;
+ }
};
// Identifier and value variant of EnumExprField AST node
class EnumExprFieldIdentifierValue : public EnumExprFieldWithVal
{
Identifier field_name;
-
- // TODO: should this store location data?
+ Location locus;
public:
EnumExprFieldIdentifierValue (Identifier field_name,
- std::unique_ptr<Expr> field_value)
+ std::unique_ptr<Expr> field_value, Location locus)
: EnumExprFieldWithVal (std::move (field_value)),
- field_name (std::move (field_name))
+ field_name (std::move (field_name)), locus (locus)
{}
- // copy constructor, destructor, and assignment operator should not need
- // defining
+ std::string as_string () const override;
void accept_vis (ASTVisitor &vis) override;
+ Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1871,16 +2066,21 @@ class EnumExprFieldIndexValue : public EnumExprFieldWithVal
TupleIndex index;
// TODO: implement "with val" as a template with EnumExprField as type param?
- // TODO: should this store location data?
+ Location locus;
public:
EnumExprFieldIndexValue (TupleIndex field_index,
- std::unique_ptr<Expr> field_value)
- : EnumExprFieldWithVal (std::move (field_value)), index (field_index)
+ std::unique_ptr<Expr> field_value, Location locus)
+ : EnumExprFieldWithVal (std::move (field_value)), index (field_index), locus (locus)
{}
+ std::string as_string () const override;
+
void accept_vis (ASTVisitor &vis) override;
+ Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1893,18 +2093,12 @@ protected:
// Struct-like syntax enum variant instance creation AST node
class EnumExprStruct : public EnumVariantExpr
{
- // std::vector<EnumExprField> fields;
std::vector<std::unique_ptr<EnumExprField> > fields;
-
Location locus;
public:
std::string as_string () const override;
- /*inline std::vector<std::unique_ptr<EnumExprField>> get_fields() const
- { return fields;
- }*/
-
EnumExprStruct (PathInExpression enum_variant_path,
std::vector<std::unique_ptr<EnumExprField> > variant_fields,
std::vector<Attribute> outer_attribs, Location locus)
@@ -1944,14 +2138,14 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- EnumExprStruct *clone_expr_impl () const override
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<std::unique_ptr<EnumExprField> > &get_fields () { return fields; }
+ const std::vector<std::unique_ptr<EnumExprField> > &get_fields () const
{
- return new EnumExprStruct (*this);
+ return fields;
}
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
EnumExprStruct *clone_expr_without_block_impl () const override
@@ -1970,10 +2164,6 @@ class EnumExprTuple : public EnumVariantExpr
public:
std::string as_string () const override;
- /*inline std::vector<std::unique_ptr<Expr>> get_values() const {
- return values;
- }*/
-
EnumExprTuple (PathInExpression enum_variant_path,
std::vector<std::unique_ptr<Expr> > variant_values,
std::vector<Attribute> outer_attribs, Location locus)
@@ -2013,14 +2203,13 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- EnumExprTuple *clone_expr_impl () const override
+ const std::vector<std::unique_ptr<Expr> > &get_elems () const
{
- return new EnumExprTuple (*this);
+ return values;
}
+ std::vector<std::unique_ptr<Expr> > &get_elems () { return values; }
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
EnumExprTuple *clone_expr_without_block_impl () const override
@@ -2056,13 +2245,6 @@ public:
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
- EnumExprFieldless *clone_expr_impl () const override
- {
- return new EnumExprFieldless (*this);
- }
-
- /* Use covariance to implement clone function as returning this object rather
- * than base */
EnumExprFieldless *clone_expr_without_block_impl () const override
{
return new EnumExprFieldless (*this);
@@ -2075,21 +2257,17 @@ class Function;
// Function call expression AST node
class CallExpr : public ExprWithoutBlock
{
-public:
std::unique_ptr<Expr> function;
// inlined form of CallParams
std::vector<std::unique_ptr<Expr> > params;
Location locus;
+public:
Function *fndeclRef;
std::string as_string () const override;
- /*inline std::vector<std::unique_ptr<Expr>> get_params() const {
- return params;
- }*/
-
CallExpr (std::unique_ptr<Expr> function_expr,
std::vector<std::unique_ptr<Expr> > function_params,
std::vector<Attribute> outer_attribs, Location locus)
@@ -2100,9 +2278,12 @@ public:
// copy constructor requires clone
CallExpr (CallExpr const &other)
- : ExprWithoutBlock (other), function (other.function->clone_expr ()),
- locus (other.locus)
- /*, params(other.params),*/ {
+ : ExprWithoutBlock (other), locus (other.locus)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.function != nullptr)
+ function = other.function->clone_expr ();
+
params.reserve (other.params.size ());
for (const auto &e : other.params)
params.push_back (e->clone_expr ());
@@ -2112,11 +2293,15 @@ public:
CallExpr &operator= (CallExpr const &other)
{
ExprWithoutBlock::operator= (other);
- function = other.function->clone_expr ();
locus = other.locus;
- // params = other.params;
// outer_attrs = other.outer_attrs;
+ // guard to prevent null dereference (only required if error state)
+ if (other.function != nullptr)
+ function = other.function->clone_expr ();
+ else
+ function = nullptr;
+
params.reserve (other.params.size ());
for (const auto &e : other.params)
params.push_back (e->clone_expr ());
@@ -2136,11 +2321,25 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- CallExpr *clone_expr_impl () const override { return new CallExpr (*this); }
+ // Invalid if function expr is null, so base stripping on that.
+ void mark_for_strip () override { function = nullptr; }
+ bool is_marked_for_strip () const override { return function == nullptr; }
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ const std::vector<std::unique_ptr<Expr> > &get_params () const
+ {
+ return params;
+ }
+ std::vector<std::unique_ptr<Expr> > &get_params () { return params; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_function_expr ()
+ {
+ rust_assert (function != nullptr);
+ return function;
+ }
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
CallExpr *clone_expr_without_block_impl () const override
@@ -2162,10 +2361,6 @@ class MethodCallExpr : public ExprWithoutBlock
public:
std::string as_string () const override;
- /*inline std::vector<std::unique_ptr<Expr>> get_params() const {
- return params;
- }*/
-
MethodCallExpr (std::unique_ptr<Expr> call_receiver,
PathExprSegment method_path,
std::vector<std::unique_ptr<Expr> > method_params,
@@ -2178,9 +2373,13 @@ public:
// copy constructor required due to cloning
MethodCallExpr (MethodCallExpr const &other)
- : ExprWithoutBlock (other), receiver (other.receiver->clone_expr ()),
- method_name (other.method_name), locus (other.locus)
- /*, params(other.params),*/ {
+ : ExprWithoutBlock (other), method_name (other.method_name),
+ locus (other.locus)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.receiver != nullptr)
+ receiver = other.receiver->clone_expr ();
+
params.reserve (other.params.size ());
for (const auto &e : other.params)
params.push_back (e->clone_expr ());
@@ -2190,12 +2389,16 @@ public:
MethodCallExpr &operator= (MethodCallExpr const &other)
{
ExprWithoutBlock::operator= (other);
- receiver = other.receiver->clone_expr ();
method_name = other.method_name;
locus = other.locus;
- // params = other.params;
// outer_attrs = other.outer_attrs;
+ // guard to prevent null dereference (only required if error state)
+ if (other.receiver != nullptr)
+ receiver = other.receiver->clone_expr ();
+ else
+ receiver = nullptr;
+
params.reserve (other.params.size ());
for (const auto &e : other.params)
params.push_back (e->clone_expr ());
@@ -2212,14 +2415,28 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- MethodCallExpr *clone_expr_impl () const override
+ // Invalid if receiver expr is null, so base stripping on that.
+ void mark_for_strip () override { receiver = nullptr; }
+ bool is_marked_for_strip () const override { return receiver == nullptr; }
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ const std::vector<std::unique_ptr<Expr> > &get_params () const
{
- return new MethodCallExpr (*this);
+ return params;
}
+ std::vector<std::unique_ptr<Expr> > &get_params () { return params; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_receiver_expr ()
+ {
+ rust_assert (receiver != nullptr);
+ return receiver;
+ }
+
+ const PathExprSegment &get_method_name () const { return method_name; }
+ PathExprSegment &get_method_name () { return method_name; }
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
MethodCallExpr *clone_expr_without_block_impl () const override
@@ -2250,19 +2467,27 @@ public:
// Copy constructor required due to unique_ptr cloning
FieldAccessExpr (FieldAccessExpr const &other)
- : ExprWithoutBlock (other), receiver (other.receiver->clone_expr ()),
- field (other.field), locus (other.locus)
- {}
+ : ExprWithoutBlock (other), field (other.field), locus (other.locus)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.receiver != nullptr)
+ receiver = other.receiver->clone_expr ();
+ }
// Overload assignment operator to clone unique_ptr
FieldAccessExpr &operator= (FieldAccessExpr const &other)
{
ExprWithoutBlock::operator= (other);
- receiver = other.receiver->clone_expr ();
field = other.field;
locus = other.locus;
// outer_attrs = other.outer_attrs;
+ // guard to prevent null dereference (only required if error state)
+ if (other.receiver != nullptr)
+ receiver = other.receiver->clone_expr ();
+ else
+ receiver = nullptr;
+
return *this;
}
@@ -2275,14 +2500,20 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- FieldAccessExpr *clone_expr_impl () const override
+ // Invalid if receiver expr is null, so base stripping on that.
+ void mark_for_strip () override { receiver = nullptr; }
+ bool is_marked_for_strip () const override { return receiver == nullptr; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_receiver_expr ()
{
- return new FieldAccessExpr (*this);
+ rust_assert (receiver != nullptr);
+ return receiver;
}
+ Identifier get_field_name () const { return field; }
+
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
FieldAccessExpr *clone_expr_without_block_impl () const override
@@ -2295,6 +2526,7 @@ protected:
struct ClosureParam
{
private:
+ std::vector<Attribute> outer_attrs;
std::unique_ptr<Pattern> pattern;
// bool has_type_given;
@@ -2306,17 +2538,22 @@ public:
// Returns whether the type of the parameter has been given.
bool has_type_given () const { return type != nullptr; }
+ bool has_outer_attrs () const { return !outer_attrs.empty (); }
+
// Constructor for closure parameter
ClosureParam (std::unique_ptr<Pattern> param_pattern,
- std::unique_ptr<Type> param_type = nullptr)
- : pattern (std::move (param_pattern)), type (std::move (param_type))
+ std::unique_ptr<Type> param_type = nullptr,
+ std::vector<Attribute> outer_attrs = {})
+ : outer_attrs (std::move (outer_attrs)),
+ pattern (std::move (param_pattern)), type (std::move (param_type))
{}
// Copy constructor required due to cloning as a result of unique_ptrs
- ClosureParam (ClosureParam const &other)
- : pattern (other.pattern->clone_pattern ())
+ ClosureParam (ClosureParam const &other) : outer_attrs (other.outer_attrs)
{
// guard to protect from null pointer dereference
+ if (other.pattern != nullptr)
+ pattern = other.pattern->clone_pattern ();
if (other.type != nullptr)
type = other.type->clone_type ();
}
@@ -2326,8 +2563,17 @@ public:
// Assignment operator must be overloaded to clone as well
ClosureParam &operator= (ClosureParam const &other)
{
- pattern = other.pattern->clone_pattern ();
- type = other.type->clone_type ();
+ outer_attrs = other.outer_attrs;
+
+ // guard to protect from null pointer dereference
+ if (other.pattern != nullptr)
+ pattern = other.pattern->clone_pattern ();
+ else
+ pattern = nullptr;
+ if (other.type != nullptr)
+ type = other.type->clone_type ();
+ else
+ type = nullptr;
return *this;
}
@@ -2343,6 +2589,23 @@ public:
static ClosureParam create_error () { return ClosureParam (nullptr); }
std::string as_string () const;
+
+ const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+ std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Pattern> &get_pattern ()
+ {
+ rust_assert (pattern != nullptr);
+ return pattern;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type ()
+ {
+ rust_assert (has_type_given ());
+ return type;
+ }
};
// Base closure definition expression AST node - abstract
@@ -2367,6 +2630,10 @@ public:
Location get_locus () const { return locus; }
Location get_locus_slow () const override { return get_locus (); }
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ const std::vector<ClosureParam> &get_params () const { return params; }
+ std::vector<ClosureParam> &get_params () { return params; }
};
// Represents a non-type-specified closure expression AST node
@@ -2389,19 +2656,27 @@ public:
{}
// Copy constructor must be defined to allow copying via cloning of unique_ptr
- ClosureExprInner (ClosureExprInner const &other)
- : ClosureExpr (other), closure_inner (other.closure_inner->clone_expr ())
- {}
+ ClosureExprInner (ClosureExprInner const &other) : ClosureExpr (other)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.closure_inner != nullptr)
+ closure_inner = other.closure_inner->clone_expr ();
+ }
// Overload assignment operator to clone closure_inner
ClosureExprInner &operator= (ClosureExprInner const &other)
{
ClosureExpr::operator= (other);
- closure_inner = other.closure_inner->clone_expr ();
// params = other.params;
// has_move = other.has_move;
// outer_attrs = other.outer_attrs;
+ // guard to prevent null dereference (only required if error state)
+ if (other.closure_inner != nullptr)
+ closure_inner = other.closure_inner->clone_expr ();
+ else
+ closure_inner = nullptr;
+
return *this;
}
@@ -2411,14 +2686,21 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- ClosureExprInner *clone_expr_impl () const override
+ // Invalid if inner expr is null, so base stripping on that.
+ void mark_for_strip () override { closure_inner = nullptr; }
+ bool is_marked_for_strip () const override
{
- return new ClosureExprInner (*this);
+ return closure_inner == nullptr;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_definition_expr ()
+ {
+ rust_assert (closure_inner != nullptr);
+ return closure_inner;
}
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
ClosureExprInner *clone_expr_without_block_impl () const override
@@ -2430,7 +2712,6 @@ protected:
// A block AST node
class BlockExpr : public ExprWithBlock
{
-public:
std::vector<Attribute> inner_attrs;
// bool has_statements;
@@ -2439,14 +2720,16 @@ public:
std::unique_ptr<ExprWithoutBlock> expr; // inlined from Statements
Location locus;
+ bool marked_for_strip = false;
+public:
std::string as_string () const override;
// Returns whether the block contains statements.
bool has_statements () const { return !statements.empty (); }
- // Returns whether the block contains an expression
- bool has_expr () const { return expr != nullptr; }
+ // Returns whether the block contains a final expression.
+ bool has_tail_expr () const { return expr != nullptr; }
BlockExpr (std::vector<std::unique_ptr<Stmt> > block_statements,
std::unique_ptr<ExprWithoutBlock> block_expr,
@@ -2460,8 +2743,8 @@ public:
// Copy constructor with clone
BlockExpr (BlockExpr const &other)
- : ExprWithBlock (other), /*statements(other.statements),*/
- inner_attrs (other.inner_attrs), locus (other.locus)
+ : ExprWithBlock (other), inner_attrs (other.inner_attrs),
+ locus (other.locus), marked_for_strip (other.marked_for_strip)
{
// guard to protect from null pointer dereference
if (other.expr != nullptr)
@@ -2476,12 +2759,17 @@ public:
BlockExpr &operator= (BlockExpr const &other)
{
ExprWithBlock::operator= (other);
- // statements = other.statements;
- expr = other.expr->clone_expr_without_block ();
inner_attrs = other.inner_attrs;
locus = other.locus;
+ marked_for_strip = other.marked_for_strip;
// outer_attrs = other.outer_attrs;
+ // guard to protect from null pointer dereference
+ if (other.expr != nullptr)
+ expr = other.expr->clone_expr_without_block ();
+ else
+ expr = nullptr;
+
statements.reserve (other.statements.size ());
for (const auto &e : other.statements)
statements.push_back (e->clone_stmt ());
@@ -2500,18 +2788,41 @@ public:
}
Location get_locus () const { return locus; }
- Location get_locus_slow () const override { return get_locus (); }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- BlockExpr *clone_expr_impl () const override
+ // Can be completely empty, so have to have a separate flag.
+ void mark_for_strip () override
{
- return clone_block_expr_impl ();
+ marked_for_strip = true;
+ }
+ bool is_marked_for_strip () const override
+ {
+ return marked_for_strip;
+ }
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
+ std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
+
+ const std::vector<std::unique_ptr<Stmt> > &get_statements () const
+ {
+ return statements;
}
+ std::vector<std::unique_ptr<Stmt> > &get_statements () { return statements; }
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<ExprWithoutBlock> &get_tail_expr ()
+ {
+ rust_assert (has_tail_expr ());
+ return expr;
+ }
+
+ // Removes the tail expression from the block.
+ void strip_tail_expr () { expr = nullptr; }
+
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
BlockExpr *clone_expr_with_block_impl () const override
@@ -2530,6 +2841,7 @@ protected:
// Represents a type-specified closure expression AST node
class ClosureExprInnerTyped : public ClosureExpr
{
+ // TODO: spec says typenobounds
std::unique_ptr<Type> return_type;
std::unique_ptr<BlockExpr>
expr; // only used because may be polymorphic in future
@@ -2552,20 +2864,33 @@ public:
// Copy constructor requires cloning
ClosureExprInnerTyped (ClosureExprInnerTyped const &other)
- : ClosureExpr (other), return_type (other.return_type->clone_type ()),
- expr (other.expr->clone_block_expr ())
- {}
+ : ClosureExpr (other)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.expr != nullptr)
+ expr = other.expr->clone_block_expr ();
+ if (other.return_type != nullptr)
+ return_type = other.return_type->clone_type ();
+ }
// Overload assignment operator to clone unique_ptrs
ClosureExprInnerTyped &operator= (ClosureExprInnerTyped const &other)
{
ClosureExpr::operator= (other);
- return_type = other.return_type->clone_type ();
- expr = other.expr->clone_block_expr ();
// params = other.params;
// has_move = other.has_move;
// outer_attrs = other.outer_attrs;
+ // guard to prevent null dereference (only required if error state)
+ if (other.expr != nullptr)
+ expr = other.expr->clone_block_expr ();
+ else
+ expr = nullptr;
+ if (other.return_type != nullptr)
+ return_type = other.return_type->clone_type ();
+ else
+ return_type = nullptr;
+
return *this;
}
@@ -2575,14 +2900,26 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- ClosureExprInnerTyped *clone_expr_impl () const override
+ /* Invalid if inner expr is null, so base stripping on that. Technically,
+ * type should also not be null. */
+ void mark_for_strip () override { expr = nullptr; }
+ bool is_marked_for_strip () const override { return expr == nullptr; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<BlockExpr> &get_definition_block ()
{
- return new ClosureExprInnerTyped (*this);
+ rust_assert (expr != nullptr);
+ return expr;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_return_type ()
+ {
+ rust_assert (return_type != nullptr);
+ return return_type;
}
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
ClosureExprInnerTyped *clone_expr_without_block_impl () const override
@@ -2598,6 +2935,9 @@ class ContinueExpr : public ExprWithoutBlock
Lifetime label;
Location locus;
+ // TODO: find another way to store this to save memory?
+ bool marked_for_strip = false;
+
public:
std::string as_string () const override;
@@ -2617,14 +2957,11 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- ContinueExpr *clone_expr_impl () const override
- {
- return new ContinueExpr (*this);
- }
+ // Can't think of any invalid invariants, so store boolean.
+ void mark_for_strip () override { marked_for_strip = true; }
+ bool is_marked_for_strip () const override { return marked_for_strip; }
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
ContinueExpr *clone_expr_without_block_impl () const override
@@ -2645,6 +2982,9 @@ class BreakExpr : public ExprWithoutBlock
Location locus;
+ // TODO: find another way to store this to save memory?
+ bool marked_for_strip = false;
+
public:
std::string as_string () const override;
@@ -2666,7 +3006,8 @@ public:
// Copy constructor defined to use clone for unique pointer
BreakExpr (BreakExpr const &other)
- : ExprWithoutBlock (other), label (other.label), locus (other.locus)
+ : ExprWithoutBlock (other), label (other.label), locus (other.locus),
+ marked_for_strip (other.marked_for_strip)
{
// guard to protect from null pointer dereference
if (other.break_expr != nullptr)
@@ -2678,10 +3019,16 @@ public:
{
ExprWithoutBlock::operator= (other);
label = other.label;
- break_expr = other.break_expr->clone_expr ();
locus = other.locus;
+ marked_for_strip = other.marked_for_strip;
// outer_attrs = other.outer_attrs;
+ // guard to protect from null pointer dereference
+ if (other.break_expr != nullptr)
+ break_expr = other.break_expr->clone_expr ();
+ else
+ break_expr = nullptr;
+
return *this;
}
@@ -2694,11 +3041,18 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- BreakExpr *clone_expr_impl () const override { return new BreakExpr (*this); }
+ // Can't think of any invalid invariants, so store boolean.
+ void mark_for_strip () override { marked_for_strip = true; }
+ bool is_marked_for_strip () const override { return marked_for_strip; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_break_expr ()
+ {
+ rust_assert (break_expr != nullptr);
+ return break_expr;
+ }
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
BreakExpr *clone_expr_without_block_impl () const override
@@ -2740,17 +3094,29 @@ public:
{}
// Copy constructor with cloning
- RangeFromToExpr (RangeFromToExpr const &other)
- : RangeExpr (other), from (other.from->clone_expr ()),
- to (other.to->clone_expr ())
- {}
+ RangeFromToExpr (RangeFromToExpr const &other) : RangeExpr (other)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.from != nullptr)
+ from = other.from->clone_expr ();
+ if (other.to != nullptr)
+ to = other.to->clone_expr ();
+ }
// Overload assignment operator to clone unique pointers
RangeFromToExpr &operator= (RangeFromToExpr const &other)
{
RangeExpr::operator= (other);
- from = other.from->clone_expr ();
- to = other.to->clone_expr ();
+
+ // guard to prevent null dereference (only required if error state)
+ if (other.from != nullptr)
+ from = other.from->clone_expr ();
+ else
+ from = nullptr;
+ if (other.to != nullptr)
+ to = other.to->clone_expr ();
+ else
+ to = nullptr;
return *this;
}
@@ -2761,14 +3127,32 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- RangeFromToExpr *clone_expr_impl () const override
+ // Invalid if either expr is null, so base stripping on that.
+ void mark_for_strip () override
{
- return new RangeFromToExpr (*this);
+ from = nullptr;
+ to = nullptr;
+ }
+ bool is_marked_for_strip () const override
+ {
+ return from == nullptr && to == nullptr;
}
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_from_expr ()
+ {
+ rust_assert (from != nullptr);
+ return from;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_to_expr ()
+ {
+ rust_assert (to != nullptr);
+ return to;
+ }
+
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
RangeFromToExpr *clone_expr_without_block_impl () const override
@@ -2791,15 +3175,23 @@ public:
{}
// Copy constructor with clone
- RangeFromExpr (RangeFromExpr const &other)
- : RangeExpr (other), from (other.from->clone_expr ())
- {}
+ RangeFromExpr (RangeFromExpr const &other) : RangeExpr (other)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.from != nullptr)
+ from = other.from->clone_expr ();
+ }
// Overload assignment operator to clone unique_ptr
RangeFromExpr &operator= (RangeFromExpr const &other)
{
RangeExpr::operator= (other);
- from = other.from->clone_expr ();
+
+ // guard to prevent null dereference (only required if error state)
+ if (other.from != nullptr)
+ from = other.from->clone_expr ();
+ else
+ from = nullptr;
return *this;
}
@@ -2810,14 +3202,18 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- RangeFromExpr *clone_expr_impl () const override
+ // Invalid if expr is null, so base stripping on that.
+ void mark_for_strip () override { from = nullptr; }
+ bool is_marked_for_strip () const override { return from == nullptr; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_from_expr ()
{
- return new RangeFromExpr (*this);
+ rust_assert (from != nullptr);
+ return from;
}
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
RangeFromExpr *clone_expr_without_block_impl () const override
@@ -2841,15 +3237,23 @@ public:
{}
// Copy constructor with clone
- RangeToExpr (RangeToExpr const &other)
- : RangeExpr (other), to (other.to->clone_expr ())
- {}
+ RangeToExpr (RangeToExpr const &other) : RangeExpr (other)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.to != nullptr)
+ to = other.to->clone_expr ();
+ }
// Overload assignment operator to clone unique_ptr
RangeToExpr &operator= (RangeToExpr const &other)
{
RangeExpr::operator= (other);
- to = other.to->clone_expr ();
+
+ // guard to prevent null dereference (only required if error state)
+ if (other.to != nullptr)
+ to = other.to->clone_expr ();
+ else
+ to = nullptr;
return *this;
}
@@ -2860,14 +3264,18 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- RangeToExpr *clone_expr_impl () const override
+ // Invalid if expr is null, so base stripping on that.
+ void mark_for_strip () override { to = nullptr; }
+ bool is_marked_for_strip () const override { return to == nullptr; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_to_expr ()
{
- return new RangeToExpr (*this);
+ rust_assert (to != nullptr);
+ return to;
}
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
RangeToExpr *clone_expr_without_block_impl () const override
@@ -2880,6 +3288,9 @@ protected:
// constructs a std::ops::RangeFull object
class RangeFullExpr : public RangeExpr
{
+ // TODO: find another way to store this to save memory?
+ bool marked_for_strip = false;
+
public:
std::string as_string () const override;
@@ -2888,14 +3299,11 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- RangeFullExpr *clone_expr_impl () const override
- {
- return new RangeFullExpr (*this);
- }
+ // Can't think of any invalid invariants, so store boolean.
+ void mark_for_strip () override { marked_for_strip = true; }
+ bool is_marked_for_strip () const override { return marked_for_strip; }
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
RangeFullExpr *clone_expr_without_block_impl () const override
@@ -2922,17 +3330,29 @@ public:
// outer attributes not allowed
// Copy constructor with clone
- RangeFromToInclExpr (RangeFromToInclExpr const &other)
- : RangeExpr (other), from (other.from->clone_expr ()),
- to (other.to->clone_expr ())
- {}
+ RangeFromToInclExpr (RangeFromToInclExpr const &other) : RangeExpr (other)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.from != nullptr)
+ from = other.from->clone_expr ();
+ if (other.to != nullptr)
+ to = other.to->clone_expr ();
+ }
// Overload assignment operator to use clone
RangeFromToInclExpr &operator= (RangeFromToInclExpr const &other)
{
RangeExpr::operator= (other);
- from = other.from->clone_expr ();
- to = other.to->clone_expr ();
+
+ // guard to prevent null dereference (only required if error state)
+ if (other.from != nullptr)
+ from = other.from->clone_expr ();
+ else
+ from = nullptr;
+ if (other.to != nullptr)
+ to = other.to->clone_expr ();
+ else
+ to = nullptr;
return *this;
}
@@ -2943,14 +3363,32 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- RangeFromToInclExpr *clone_expr_impl () const override
+ // Invalid if either expr is null, so base stripping on that.
+ void mark_for_strip () override
{
- return new RangeFromToInclExpr (*this);
+ from = nullptr;
+ to = nullptr;
+ }
+ bool is_marked_for_strip () const override
+ {
+ return from == nullptr && to == nullptr;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_from_expr ()
+ {
+ rust_assert (from != nullptr);
+ return from;
}
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_to_expr ()
+ {
+ rust_assert (to != nullptr);
+ return to;
+ }
+
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
RangeFromToInclExpr *clone_expr_without_block_impl () const override
@@ -2974,15 +3412,23 @@ public:
// outer attributes not allowed
// Copy constructor with clone
- RangeToInclExpr (RangeToInclExpr const &other)
- : RangeExpr (other), to (other.to->clone_expr ())
- {}
+ RangeToInclExpr (RangeToInclExpr const &other) : RangeExpr (other)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.to != nullptr)
+ to = other.to->clone_expr ();
+ }
// Overload assignment operator to clone pointer
RangeToInclExpr &operator= (RangeToInclExpr const &other)
{
RangeExpr::operator= (other);
- to = other.to->clone_expr ();
+
+ // guard to prevent null dereference (only required if error state)
+ if (other.to != nullptr)
+ to = other.to->clone_expr ();
+ else
+ to = nullptr;
return *this;
}
@@ -2993,14 +3439,18 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- RangeToInclExpr *clone_expr_impl () const override
+ // Invalid if expr is null, so base stripping on that.
+ void mark_for_strip () override { to = nullptr; }
+ bool is_marked_for_strip () const override { return to == nullptr; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_to_expr ()
{
- return new RangeToInclExpr (*this);
+ rust_assert (to != nullptr);
+ return to;
}
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
RangeToInclExpr *clone_expr_without_block_impl () const override
@@ -3016,12 +3466,15 @@ class ReturnExpr : public ExprWithoutBlock
Location locus;
+ // TODO: find another way to store this to save memory?
+ bool marked_for_strip = false;
+
public:
std::string as_string () const override;
/* Returns whether the object has an expression returned (i.e. not void return
* type). */
- bool has_return_expr () const { return return_expr != nullptr; }
+ bool has_returned_expr () const { return return_expr != nullptr; }
// Constructor for ReturnExpr.
ReturnExpr (Location locus, std::unique_ptr<Expr> returned_expr = nullptr,
@@ -3032,7 +3485,8 @@ public:
// Copy constructor with clone
ReturnExpr (ReturnExpr const &other)
- : ExprWithoutBlock (other), locus (other.locus)
+ : ExprWithoutBlock (other), locus (other.locus),
+ marked_for_strip (other.marked_for_strip)
{
// guard to protect from null pointer dereference
if (other.return_expr != nullptr)
@@ -3043,10 +3497,16 @@ public:
ReturnExpr &operator= (ReturnExpr const &other)
{
ExprWithoutBlock::operator= (other);
- return_expr = other.return_expr->clone_expr ();
locus = other.locus;
+ marked_for_strip = other.marked_for_strip;
// outer_attrs = other.outer_attrs;
+ // guard to protect from null pointer dereference
+ if (other.return_expr != nullptr)
+ return_expr = other.return_expr->clone_expr ();
+ else
+ return_expr = nullptr;
+
return *this;
}
@@ -3059,16 +3519,18 @@ public:
void accept_vis (ASTVisitor &vis) override;
- Expr *get_expr () { return return_expr.get (); }
+ // Can't think of any invalid invariants, so store boolean.
+ void mark_for_strip () override { marked_for_strip = true; }
+ bool is_marked_for_strip () const override { return marked_for_strip; }
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- ReturnExpr *clone_expr_impl () const override
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_returned_expr ()
{
- return new ReturnExpr (*this);
+ rust_assert (return_expr != nullptr);
+ return return_expr;
}
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
ReturnExpr *clone_expr_without_block_impl () const override
@@ -3085,7 +3547,6 @@ class UnsafeBlockExpr : public ExprWithBlock
{
// Or just have it extend BlockExpr
std::unique_ptr<BlockExpr> expr;
-
Location locus;
public:
@@ -3099,18 +3560,26 @@ public:
// Copy constructor with clone
UnsafeBlockExpr (UnsafeBlockExpr const &other)
- : ExprWithBlock (other), expr (other.expr->clone_block_expr ()),
- locus (other.locus)
- {}
+ : ExprWithBlock (other), locus (other.locus)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.expr != nullptr)
+ expr = other.expr->clone_block_expr ();
+ }
// Overloaded assignment operator to clone
UnsafeBlockExpr &operator= (UnsafeBlockExpr const &other)
{
ExprWithBlock::operator= (other);
- expr = other.expr->clone_block_expr ();
locus = other.locus;
// outer_attrs = other.outer_attrs;
+ // guard to prevent null dereference (only required if error state)
+ if (other.expr != nullptr)
+ expr = other.expr->clone_block_expr ();
+ else
+ expr = nullptr;
+
return *this;
}
@@ -3123,14 +3592,18 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- UnsafeBlockExpr *clone_expr_impl () const override
+ // Invalid if block is null, so base stripping on that.
+ void mark_for_strip () override { expr = nullptr; }
+ bool is_marked_for_strip () const override { return expr == nullptr; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<BlockExpr> &get_block_expr ()
{
- return new UnsafeBlockExpr (*this);
+ rust_assert (expr != nullptr);
+ return expr;
}
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
UnsafeBlockExpr *clone_expr_with_block_impl () const override
@@ -3144,7 +3617,6 @@ protected:
class LoopLabel /*: public Node*/
{
Lifetime label; // or type LIFETIME_OR_LABEL
-
Location locus;
public:
@@ -3189,19 +3661,27 @@ protected:
// Copy constructor for BaseLoopExpr with clone
BaseLoopExpr (BaseLoopExpr const &other)
- : ExprWithBlock (other), loop_label (other.loop_label),
- loop_block (other.loop_block->clone_block_expr ()), locus (other.locus)
- {}
+ : ExprWithBlock (other), loop_label (other.loop_label), locus (other.locus)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.loop_block != nullptr)
+ loop_block = other.loop_block->clone_block_expr ();
+ }
// Overloaded assignment operator to clone
BaseLoopExpr &operator= (BaseLoopExpr const &other)
{
ExprWithBlock::operator= (other);
- loop_block = other.loop_block->clone_block_expr ();
loop_label = other.loop_label;
locus = other.locus;
// outer_attrs = other.outer_attrs;
+ // guard to prevent null dereference (only required if error state)
+ if (other.loop_block != nullptr)
+ loop_block = other.loop_block->clone_block_expr ();
+ else
+ loop_block = nullptr;
+
return *this;
}
@@ -3214,6 +3694,17 @@ public:
Location get_locus () const { return locus; }
Location get_locus_slow () const override { return get_locus (); }
+
+ // Invalid if loop block is null, so base stripping on that.
+ void mark_for_strip () override { loop_block = nullptr; }
+ bool is_marked_for_strip () const override { return loop_block == nullptr; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<BlockExpr> &get_loop_block ()
+ {
+ rust_assert (loop_block != nullptr);
+ return loop_block;
+ }
};
// 'Loop' expression (i.e. the infinite loop) AST node
@@ -3235,10 +3726,6 @@ public:
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
- LoopExpr *clone_expr_impl () const override { return new LoopExpr (*this); }
-
- /* Use covariance to implement clone function as returning this object rather
- * than base */
LoopExpr *clone_expr_with_block_impl () const override
{
return new LoopExpr (*this);
@@ -3287,14 +3774,14 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- WhileLoopExpr *clone_expr_impl () const override
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_predicate_expr ()
{
- return new WhileLoopExpr (*this);
+ rust_assert (condition != nullptr);
+ return condition;
}
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
WhileLoopExpr *clone_expr_with_block_impl () const override
@@ -3308,14 +3795,14 @@ class WhileLetLoopExpr : public BaseLoopExpr
{
// MatchArmPatterns patterns;
std::vector<std::unique_ptr<Pattern> > match_arm_patterns; // inlined
- std::unique_ptr<Expr> condition;
+ std::unique_ptr<Expr> scrutinee;
public:
std::string as_string () const override;
// Constructor with a loop label
WhileLetLoopExpr (std::vector<std::unique_ptr<Pattern> > match_arm_patterns,
- std::unique_ptr<Expr> condition,
+ std::unique_ptr<Expr> scrutinee,
std::unique_ptr<BlockExpr> loop_block, Location locus,
LoopLabel loop_label = LoopLabel::error (),
std::vector<Attribute> outer_attribs
@@ -3323,14 +3810,14 @@ public:
: BaseLoopExpr (std::move (loop_block), locus, std::move (loop_label),
std::move (outer_attribs)),
match_arm_patterns (std::move (match_arm_patterns)),
- condition (std::move (condition))
+ scrutinee (std::move (scrutinee))
{}
// Copy constructor with clone
WhileLetLoopExpr (WhileLetLoopExpr const &other)
: BaseLoopExpr (other),
- /*match_arm_patterns(other.match_arm_patterns),*/ condition (
- other.condition->clone_expr ())
+ /*match_arm_patterns(other.match_arm_patterns),*/ scrutinee (
+ other.scrutinee->clone_expr ())
{
match_arm_patterns.reserve (other.match_arm_patterns.size ());
for (const auto &e : other.match_arm_patterns)
@@ -3342,7 +3829,7 @@ public:
{
BaseLoopExpr::operator= (other);
// match_arm_patterns = other.match_arm_patterns;
- condition = other.condition->clone_expr ();
+ scrutinee = other.scrutinee->clone_expr ();
// loop_block = other.loop_block->clone_block_expr();
// loop_label = other.loop_label;
// outer_attrs = other.outer_attrs;
@@ -3360,14 +3847,24 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- WhileLetLoopExpr *clone_expr_impl () const override
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_scrutinee_expr ()
{
- return new WhileLetLoopExpr (*this);
+ rust_assert (scrutinee != nullptr);
+ return scrutinee;
}
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ const std::vector<std::unique_ptr<Pattern> > &get_patterns () const
+ {
+ return match_arm_patterns;
+ }
+ std::vector<std::unique_ptr<Pattern> > &get_patterns ()
+ {
+ return match_arm_patterns;
+ }
+
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
WhileLetLoopExpr *clone_expr_with_block_impl () const override
@@ -3422,14 +3919,21 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- ForLoopExpr *clone_expr_impl () const override
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_iterator_expr ()
{
- return new ForLoopExpr (*this);
+ rust_assert (iterator_expr != nullptr);
+ return iterator_expr;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Pattern> &get_pattern ()
+ {
+ rust_assert (pattern != nullptr);
+ return pattern;
}
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
ForLoopExpr *clone_expr_with_block_impl () const override
@@ -3461,19 +3965,31 @@ public:
// outer attributes are never allowed on IfExprs
// Copy constructor with clone
- IfExpr (IfExpr const &other)
- : ExprWithBlock (other), condition (other.condition->clone_expr ()),
- if_block (other.if_block->clone_block_expr ()), locus (other.locus)
- {}
+ IfExpr (IfExpr const &other) : ExprWithBlock (other), locus (other.locus)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.condition != nullptr)
+ condition = other.condition->clone_expr ();
+ if (other.if_block != nullptr)
+ if_block = other.if_block->clone_block_expr ();
+ }
// Overloaded assignment operator to clone expressions
IfExpr &operator= (IfExpr const &other)
{
ExprWithBlock::operator= (other);
- condition = other.condition->clone_expr ();
- if_block = other.if_block->clone_block_expr ();
locus = other.locus;
+ // guard to prevent null dereference (only required if error state)
+ if (other.condition != nullptr)
+ condition = other.condition->clone_expr ();
+ else
+ condition = nullptr;
+ if (other.if_block != nullptr)
+ if_block = other.if_block->clone_block_expr ();
+ else
+ if_block = nullptr;
+
return *this;
}
@@ -3499,22 +4015,40 @@ public:
void vis_if_condition (ASTVisitor &vis) { condition->accept_vis (vis); }
void vis_if_block (ASTVisitor &vis) { if_block->accept_vis (vis); }
- Expr *get_if_condition () { return condition.get (); }
- BlockExpr *get_if_block () { return if_block.get (); }
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_condition_expr ()
+ {
+ rust_assert (condition != nullptr);
+ return condition;
+ }
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- IfExpr *clone_expr_impl () const override { return new IfExpr (*this); }
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<BlockExpr> &get_if_block ()
+ {
+ rust_assert (if_block != nullptr);
+ return if_block;
+ }
+ // Invalid if if block or condition is null, so base stripping on that.
+ void mark_for_strip () override
+ {
+ if_block = nullptr;
+ condition = nullptr;
+ }
+ bool is_marked_for_strip () const override
+ {
+ return if_block == nullptr && condition == nullptr;
+ }
+
+protected:
// Base clone function but still concrete as concrete base class
virtual IfExpr *clone_if_expr_impl () const { return new IfExpr (*this); }
/* Use covariance to implement clone function as returning this object rather
* than base */
- IfExpr *clone_expr_with_block_impl () const override
+ IfExpr *clone_expr_with_block_impl () const final override
{
- return new IfExpr (*this);
+ return clone_if_expr_impl ();
}
};
@@ -3558,21 +4092,14 @@ public:
void vis_else_block (ASTVisitor &vis) { else_block->accept_vis (vis); }
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- IfExprConseqElse *clone_expr_impl () const override
- {
- return new IfExprConseqElse (*this);
- }
-
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- IfExprConseqElse *clone_expr_with_block_impl () const override
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<BlockExpr> &get_else_block ()
{
- return new IfExprConseqElse (*this);
+ rust_assert (else_block != nullptr);
+ return else_block;
}
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
IfExprConseqElse *clone_if_expr_impl () const override
@@ -3624,21 +4151,14 @@ public:
conseq_if_expr->accept_vis (vis);
}
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- IfExprConseqIf *clone_expr_impl () const override
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<IfExpr> &get_conseq_if_expr ()
{
- return new IfExprConseqIf (*this);
- }
-
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- IfExprConseqIf *clone_expr_with_block_impl () const override
- {
- return new IfExprConseqIf (*this);
+ rust_assert (conseq_if_expr != nullptr);
+ return conseq_if_expr;
}
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
IfExprConseqIf *clone_if_expr_impl () const override
@@ -3654,7 +4174,6 @@ class IfLetExpr : public ExprWithBlock
std::vector<std::unique_ptr<Pattern> > match_arm_patterns; // inlined
std::unique_ptr<Expr> value;
std::unique_ptr<BlockExpr> if_block;
-
Location locus;
public:
@@ -3671,11 +4190,14 @@ public:
// copy constructor with clone
IfLetExpr (IfLetExpr const &other)
- : ExprWithBlock (other),
- /*match_arm_patterns(other.match_arm_patterns),*/ value (
- other.value->clone_expr ()),
- if_block (other.if_block->clone_block_expr ()), locus (other.locus)
+ : ExprWithBlock (other), locus (other.locus)
{
+ // guard to prevent null dereference (only required if error state)
+ if (other.value != nullptr)
+ value = other.value->clone_expr ();
+ if (other.if_block != nullptr)
+ if_block = other.if_block->clone_block_expr ();
+
match_arm_patterns.reserve (other.match_arm_patterns.size ());
for (const auto &e : other.match_arm_patterns)
match_arm_patterns.push_back (e->clone_pattern ());
@@ -3685,11 +4207,18 @@ public:
IfLetExpr &operator= (IfLetExpr const &other)
{
ExprWithBlock::operator= (other);
- // match_arm_patterns = other.match_arm_patterns;
- value = other.value->clone_expr ();
- if_block = other.if_block->clone_block_expr ();
locus = other.locus;
+ // guard to prevent null dereference (only required if error state)
+ if (other.value != nullptr)
+ value = other.value->clone_expr ();
+ else
+ value = nullptr;
+ if (other.if_block != nullptr)
+ if_block = other.if_block->clone_block_expr ();
+ else
+ if_block = nullptr;
+
match_arm_patterns.reserve (other.match_arm_patterns.size ());
for (const auto &e : other.match_arm_patterns)
match_arm_patterns.push_back (e->clone_pattern ());
@@ -3712,16 +4241,47 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- IfLetExpr *clone_expr_impl () const override { return new IfLetExpr (*this); }
+ // Invalid if block or value is null, so base stripping on that.
+ void mark_for_strip () override
+ {
+ if_block = nullptr;
+ value = nullptr;
+ }
+ bool is_marked_for_strip () const override
+ {
+ return if_block == nullptr && value == nullptr;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_value_expr ()
+ {
+ rust_assert (value != nullptr);
+ return value;
+ }
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<BlockExpr> &get_if_block ()
+ {
+ rust_assert (if_block != nullptr);
+ return if_block;
+ }
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ const std::vector<std::unique_ptr<Pattern> > &get_patterns () const
+ {
+ return match_arm_patterns;
+ }
+ std::vector<std::unique_ptr<Pattern> > &get_patterns ()
+ {
+ return match_arm_patterns;
+ }
+
+protected:
/* Use covariance to implement clone function as returning this object rather
- * than base */
- IfLetExpr *clone_expr_with_block_impl () const override
+ * than base (or rather this or any derived object) */
+ IfLetExpr *clone_expr_with_block_impl () const final override
{
- return new IfLetExpr (*this);
+ return clone_if_let_expr_impl ();
}
// Base clone function but still concrete as concrete base class
@@ -3770,21 +4330,14 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- IfExprConseqIfLet *clone_expr_impl () const override
- {
- return new IfExprConseqIfLet (*this);
- }
-
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- IfExprConseqIfLet *clone_expr_with_block_impl () const override
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<IfLetExpr> &get_conseq_if_let_expr ()
{
- return new IfExprConseqIfLet (*this);
+ rust_assert (if_let_expr != nullptr);
+ return if_let_expr;
}
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
IfExprConseqIfLet *clone_if_expr_impl () const override
@@ -3836,21 +4389,14 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- IfLetExprConseqElse *clone_expr_impl () const override
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<BlockExpr> &get_else_block ()
{
- return new IfLetExprConseqElse (*this);
- }
-
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- IfLetExprConseqElse *clone_expr_with_block_impl () const override
- {
- return new IfLetExprConseqElse (*this);
+ rust_assert (else_block != nullptr);
+ return else_block;
}
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
IfLetExprConseqElse *clone_if_let_expr_impl () const override
@@ -3901,21 +4447,14 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- IfLetExprConseqIf *clone_expr_impl () const override
- {
- return new IfLetExprConseqIf (*this);
- }
-
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- IfLetExprConseqIf *clone_expr_with_block_impl () const override
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<IfExpr> &get_conseq_if_expr ()
{
- return new IfLetExprConseqIf (*this);
+ rust_assert (if_expr != nullptr);
+ return if_expr;
}
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
IfLetExprConseqIf *clone_if_let_expr_impl () const override
@@ -3966,21 +4505,14 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- IfLetExprConseqIfLet *clone_expr_impl () const override
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<IfLetExpr> &get_conseq_if_let_expr ()
{
- return new IfLetExprConseqIfLet (*this);
- }
-
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- IfLetExprConseqIfLet *clone_expr_with_block_impl () const override
- {
- return new IfLetExprConseqIfLet (*this);
+ rust_assert (if_let_expr != nullptr);
+ return if_let_expr;
}
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
IfLetExprConseqIfLet *clone_if_let_expr_impl () const override
@@ -4037,6 +4569,8 @@ public:
if (other.guard_expr != nullptr)
guard_expr = other.guard_expr->clone_expr ();
+ else
+ guard_expr = nullptr;
match_arm_patterns.reserve (other.match_arm_patterns.size ());
for (const auto &e : other.match_arm_patterns)
@@ -4059,6 +4593,26 @@ public:
}
std::string as_string () const;
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_guard_expr ()
+ {
+ rust_assert (has_match_arm_guard ());
+ return guard_expr;
+ }
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+ std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
+
+ const std::vector<std::unique_ptr<Pattern> > &get_patterns () const
+ {
+ return match_arm_patterns;
+ }
+ std::vector<std::unique_ptr<Pattern> > &get_patterns ()
+ {
+ return match_arm_patterns;
+ }
};
/*
@@ -4124,6 +4678,20 @@ public:
~MatchCase () = default;
std::string as_string () const;
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_expr ()
+ {
+ rust_assert (expr != nullptr);
+ return expr;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ MatchArm &get_arm ()
+ {
+ rust_assert (!arm.is_error ());
+ return arm;
+ }
};
#if 0
@@ -4249,10 +4817,13 @@ public:
// Copy constructor requires clone due to unique_ptr
MatchExpr (MatchExpr const &other)
- : ExprWithBlock (other), branch_value (other.branch_value->clone_expr ()),
- inner_attrs (other.inner_attrs), match_arms (other.match_arms),
- locus (other.locus)
+ : ExprWithBlock (other), inner_attrs (other.inner_attrs),
+ match_arms (other.match_arms), locus (other.locus)
{
+ // guard to prevent null dereference (only required if error state)
+ if (other.branch_value != nullptr)
+ branch_value = other.branch_value->clone_expr ();
+
/*match_arms.reserve (other.match_arms.size ());
for (const auto &e : other.match_arms)
match_arms.push_back (e->clone_match_case ());*/
@@ -4262,12 +4833,17 @@ public:
MatchExpr &operator= (MatchExpr const &other)
{
ExprWithBlock::operator= (other);
- branch_value = other.branch_value->clone_expr ();
inner_attrs = other.inner_attrs;
match_arms = other.match_arms;
// outer_attrs = other.outer_attrs;
locus = other.locus;
+ // guard to prevent null dereference (only required if error state)
+ if (other.branch_value != nullptr)
+ branch_value = other.branch_value->clone_expr ();
+ else
+ branch_value = nullptr;
+
/*match_arms.reserve (other.match_arms.size ());
for (const auto &e : other.match_arms)
match_arms.push_back (e->clone_match_case ());*/
@@ -4284,11 +4860,25 @@ public:
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- MatchExpr *clone_expr_impl () const override { return new MatchExpr (*this); }
+ // Invalid if branch value is null, so base stripping on that.
+ void mark_for_strip () override { branch_value = nullptr; }
+ bool is_marked_for_strip () const override { return branch_value == nullptr; }
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
+ std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_scrutinee_expr ()
+ {
+ rust_assert (branch_value != nullptr);
+ return branch_value;
+ }
+
+ const std::vector<MatchCase> &get_match_cases () const { return match_arms; }
+ std::vector<MatchCase> &get_match_cases () { return match_arms; }
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
MatchExpr *clone_expr_with_block_impl () const override
@@ -4301,7 +4891,6 @@ protected:
class AwaitExpr : public ExprWithoutBlock
{
std::unique_ptr<Expr> awaited_expr;
-
Location locus;
public:
@@ -4314,17 +4903,25 @@ public:
// copy constructor with clone
AwaitExpr (AwaitExpr const &other)
- : ExprWithoutBlock (other),
- awaited_expr (other.awaited_expr->clone_expr ()), locus (other.locus)
- {}
+ : ExprWithoutBlock (other), locus (other.locus)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.awaited_expr != nullptr)
+ awaited_expr = other.awaited_expr->clone_expr ();
+ }
// overloaded assignment operator with clone
AwaitExpr &operator= (AwaitExpr const &other)
{
ExprWithoutBlock::operator= (other);
- awaited_expr = other.awaited_expr->clone_expr ();
locus = other.locus;
+ // guard to prevent null dereference (only required if error state)
+ if (other.awaited_expr != nullptr)
+ awaited_expr = other.awaited_expr->clone_expr ();
+ else
+ awaited_expr = nullptr;
+
return *this;
}
@@ -4339,6 +4936,17 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Invalid if awaited expr is null, so base stripping on that.
+ void mark_for_strip () override { awaited_expr = nullptr; }
+ bool is_marked_for_strip () const override { return awaited_expr == nullptr; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_awaited_expr ()
+ {
+ rust_assert (awaited_expr != nullptr);
+ return awaited_expr;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -4354,7 +4962,6 @@ class AsyncBlockExpr : public ExprWithBlock
// TODO: should this extend BlockExpr rather than be a composite of it?
bool has_move;
std::unique_ptr<BlockExpr> block_expr;
-
Location locus;
public:
@@ -4366,18 +4973,26 @@ public:
// copy constructor with clone
AsyncBlockExpr (AsyncBlockExpr const &other)
- : ExprWithBlock (other), has_move (other.has_move),
- block_expr (other.block_expr->clone_block_expr ()), locus (other.locus)
- {}
+ : ExprWithBlock (other), has_move (other.has_move), locus (other.locus)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.block_expr != nullptr)
+ block_expr = other.block_expr->clone_block_expr ();
+ }
// overloaded assignment operator to clone
AsyncBlockExpr &operator= (AsyncBlockExpr const &other)
{
ExprWithBlock::operator= (other);
has_move = other.has_move;
- block_expr = other.block_expr->clone_block_expr ();
locus = other.locus;
+ // guard to prevent null dereference (only required if error state)
+ if (other.block_expr != nullptr)
+ block_expr = other.block_expr->clone_block_expr ();
+ else
+ block_expr = nullptr;
+
return *this;
}
@@ -4392,6 +5007,17 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Invalid if block is null, so base stripping on that.
+ void mark_for_strip () override { block_expr = nullptr; }
+ bool is_marked_for_strip () const override { return block_expr == nullptr; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<BlockExpr> &get_block_expr ()
+ {
+ rust_assert (block_expr != nullptr);
+ return block_expr;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index b5d9247..f18124d 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -57,7 +57,7 @@ class TypeParam : public GenericParam
// bool has_type_param_bounds;
// TypeParamBounds type_param_bounds;
- std::vector<std::unique_ptr<TypeParamBound>>
+ std::vector<std::unique_ptr<TypeParamBound> >
type_param_bounds; // inlined form
// bool has_type;
@@ -76,8 +76,8 @@ public:
bool has_outer_attribute () const { return !outer_attr.is_empty (); }
TypeParam (Identifier type_representation, Location locus = Location (),
- std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds
- = std::vector<std::unique_ptr<TypeParamBound>> (),
+ std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds
+ = std::vector<std::unique_ptr<TypeParamBound> > (),
std::unique_ptr<Type> type = nullptr,
Attribute outer_attr = Attribute::create_empty ())
: outer_attr (std::move (outer_attr)),
@@ -89,9 +89,12 @@ public:
// Copy constructor uses clone
TypeParam (TypeParam const &other)
: outer_attr (other.outer_attr),
- type_representation (other.type_representation),
- type (other.type->clone_type ()), locus (other.locus)
+ type_representation (other.type_representation), locus (other.locus)
{
+ // guard to prevent null pointer dereference
+ if (other.type != nullptr)
+ type = other.type->clone_type ();
+
type_param_bounds.reserve (other.type_param_bounds.size ());
for (const auto &e : other.type_param_bounds)
type_param_bounds.push_back (e->clone_type_param_bound ());
@@ -101,11 +104,15 @@ public:
TypeParam &operator= (TypeParam const &other)
{
type_representation = other.type_representation;
- // type_param_bounds = other.type_param_bounds;
- type = other.type->clone_type ();
outer_attr = other.outer_attr;
locus = other.locus;
+ // guard to prevent null pointer dereference
+ if (other.type != nullptr)
+ type = other.type->clone_type ();
+ else
+ type = nullptr;
+
type_param_bounds.reserve (other.type_param_bounds.size ());
for (const auto &e : other.type_param_bounds)
type_param_bounds.push_back (e->clone_type_param_bound ());
@@ -123,6 +130,24 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type ()
+ {
+ rust_assert (type != nullptr);
+ return type;
+ }
+
+ // TODO: mutable getter seems kinda dodgy
+ std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds ()
+ {
+ return type_param_bounds;
+ }
+ const std::vector<std::unique_ptr<TypeParamBound> > &
+ get_type_param_bounds () const
+ {
+ return type_param_bounds;
+ }
+
protected:
// Clone function implementation as (not pure) virtual method
TypeParam *clone_generic_param_impl () const override
@@ -193,7 +218,7 @@ class TypeBoundWhereClauseItem : public WhereClauseItem
// bool has_type_param_bounds;
// TypeParamBounds type_param_bounds;
- std::vector<std::unique_ptr<TypeParamBound>>
+ std::vector<std::unique_ptr<TypeParamBound> >
type_param_bounds; // inlined form
// should this store location info?
@@ -207,7 +232,7 @@ public:
TypeBoundWhereClauseItem (
std::vector<LifetimeParam> for_lifetimes, std::unique_ptr<Type> bound_type,
- std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds)
+ std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds)
: for_lifetimes (std::move (for_lifetimes)),
bound_type (std::move (bound_type)),
type_param_bounds (std::move (type_param_bounds))
@@ -245,6 +270,24 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type ()
+ {
+ rust_assert (bound_type != nullptr);
+ return bound_type;
+ }
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds ()
+ {
+ return type_param_bounds;
+ }
+ const std::vector<std::unique_ptr<TypeParamBound> > &
+ get_type_param_bounds () const
+ {
+ return type_param_bounds;
+ }
+
protected:
// Clone function implementation as (not pure) virtual method
TypeBoundWhereClauseItem *clone_where_clause_item_impl () const override
@@ -257,13 +300,13 @@ protected:
struct WhereClause
{
private:
- std::vector<std::unique_ptr<WhereClauseItem>> where_clause_items;
+ std::vector<std::unique_ptr<WhereClauseItem> > where_clause_items;
// should this store location info?
public:
WhereClause (
- std::vector<std::unique_ptr<WhereClauseItem>> where_clause_items)
+ std::vector<std::unique_ptr<WhereClauseItem> > where_clause_items)
: where_clause_items (std::move (where_clause_items))
{}
@@ -292,13 +335,23 @@ public:
// Creates a WhereClause with no items.
static WhereClause create_empty ()
{
- return WhereClause (std::vector<std::unique_ptr<WhereClauseItem>> ());
+ return WhereClause (std::vector<std::unique_ptr<WhereClauseItem> > ());
}
// Returns whether the WhereClause has no items.
bool is_empty () const { return where_clause_items.empty (); }
std::string as_string () const;
+
+ // TODO: this mutable getter seems kinda dodgy
+ std::vector<std::unique_ptr<WhereClauseItem> > &get_items ()
+ {
+ return where_clause_items;
+ }
+ const std::vector<std::unique_ptr<WhereClauseItem> > &get_items () const
+ {
+ return where_clause_items;
+ }
};
// A self parameter in a method
@@ -322,6 +375,8 @@ private:
{}
// this is ok as no outside classes can ever call this
+ // TODO: self param can have outer attributes
+
public:
// Returns whether the self-param has a type field.
bool has_type () const { return type != nullptr; }
@@ -332,21 +387,15 @@ public:
// Returns whether the self-param is in an error state.
bool is_error () const
{
- return has_type () && has_lifetime ();
+ return (has_type () && has_lifetime ()) || (has_lifetime () && !has_ref);
// not having either is not an error
}
// Creates an error state self-param.
static SelfParam create_error ()
{
- /* HACK: creates a dummy type. Since it's a unique pointer, it should
- * clean it up, but it still allocates memory, which is not ideal. */
- return SelfParam (Lifetime (Lifetime::STATIC), false, false,
- new QualifiedPathInType (
- QualifiedPathInType::create_error ()));
- /* FIXME: is there a reason why I didn't just create a null pointer? Is it
- * due to error being having both a type and a lifetime? If it is, wouldn't
- * something like "not has_ref and has lifetime" for error be better? */
+ // cannot have no ref but have a lifetime at the same time
+ return SelfParam (Lifetime (Lifetime::STATIC), false, false, nullptr);
}
// Type-based self parameter (not ref, no lifetime)
@@ -373,13 +422,16 @@ public:
// Overload assignment operator to use clone
SelfParam &operator= (SelfParam const &other)
{
- if (other.type != nullptr)
- type = other.type->clone_type ();
is_mut = other.is_mut;
has_ref = other.has_ref;
lifetime = other.lifetime;
locus = other.locus;
+ if (other.type != nullptr)
+ type = other.type->clone_type ();
+ else
+ type = nullptr;
+
return *this;
}
@@ -390,6 +442,13 @@ public:
std::string as_string () const;
Location get_locus () const { return locus; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type ()
+ {
+ rust_assert (has_type ());
+ return type;
+ }
};
// Qualifiers for function, i.e. const, unsafe, extern etc.
@@ -424,7 +483,7 @@ public:
if (!this->extern_abi.empty ())
{
// having extern is required; not having it is an implementation error
- gcc_assert (has_extern);
+ rust_assert (has_extern);
}
}
@@ -434,31 +493,45 @@ public:
// A function parameter
struct FunctionParam
{
-public:
+private:
+ std::vector<Attribute> outer_attrs;
+ Location locus;
std::unique_ptr<Pattern> param_name;
std::unique_ptr<Type> type;
- Location locus;
-
+public:
FunctionParam (std::unique_ptr<Pattern> param_name,
- std::unique_ptr<Type> param_type, Location locus)
- : param_name (std::move (param_name)), type (std::move (param_type)),
- locus (locus)
+ std::unique_ptr<Type> param_type,
+ std::vector<Attribute> outer_attrs, Location locus)
+ : outer_attrs (std::move (outer_attrs)), locus (locus),
+ param_name (std::move (param_name)), type (std::move (param_type))
{}
// Copy constructor uses clone
- FunctionParam (FunctionParam const &other)
- : param_name (other.param_name->clone_pattern ()),
- type (other.type->clone_type ()), locus (other.locus)
- {}
+ FunctionParam (FunctionParam const &other) : locus (other.locus)
+ {
+ // guard to prevent nullptr dereference
+ if (other.param_name != nullptr)
+ param_name = other.param_name->clone_pattern ();
+ if (other.type != nullptr)
+ type = other.type->clone_type ();
+ }
// Overload assignment operator to use clone
FunctionParam &operator= (FunctionParam const &other)
{
- param_name = other.param_name->clone_pattern ();
- type = other.type->clone_type ();
locus = other.locus;
+ // guard to prevent nullptr dereference
+ if (other.param_name != nullptr)
+ param_name = other.param_name->clone_pattern ();
+ else
+ param_name = nullptr;
+ if (other.type != nullptr)
+ type = other.type->clone_type ();
+ else
+ type = nullptr;
+
return *this;
}
@@ -472,12 +545,30 @@ public:
// Creates an error FunctionParam.
static FunctionParam create_error ()
{
- return FunctionParam (nullptr, nullptr, Location ());
+ return FunctionParam (nullptr, nullptr, {}, Location ());
}
std::string as_string () const;
Location get_locus () const { return locus; }
+
+ // TODO: seems kinda dodgy. Think of better way.
+ std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
+ const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Pattern> &get_pattern ()
+ {
+ rust_assert (param_name != nullptr);
+ return param_name;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type ()
+ {
+ rust_assert (type != nullptr);
+ return type;
+ }
};
// Visibility of item - if the item has it, then it is some form of public
@@ -581,7 +672,7 @@ class Method : public InherentImplItem, public TraitImplItem
// bool has_generics;
// Generics generic_params;
- std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
+ std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined
SelfParam self_param;
@@ -596,7 +687,7 @@ class Method : public InherentImplItem, public TraitImplItem
// bool has_where_clause;
WhereClause where_clause;
- std::unique_ptr<BlockExpr> expr;
+ std::unique_ptr<BlockExpr> function_body;
Location locus;
@@ -604,17 +695,18 @@ public:
// Returns whether the method is in an error state.
bool is_error () const
{
- return expr == nullptr || method_name.empty () || self_param.is_error ();
+ return function_body == nullptr || method_name.empty ()
+ || self_param.is_error ();
}
// Creates an error state method.
static Method create_error ()
{
return Method ("", FunctionQualifiers (FunctionQualifiers::NONE, true),
- std::vector<std::unique_ptr<GenericParam>> (),
+ std::vector<std::unique_ptr<GenericParam> > (),
SelfParam::create_error (), std::vector<FunctionParam> (),
nullptr, WhereClause::create_empty (), nullptr,
- Visibility::create_error (), std::vector<Attribute> ());
+ Visibility::create_error (), std::vector<Attribute> (), {});
}
// Returns whether the method has generic parameters.
@@ -634,11 +726,11 @@ public:
// Mega-constructor with all possible fields
Method (Identifier method_name, FunctionQualifiers qualifiers,
- std::vector<std::unique_ptr<GenericParam>> generic_params,
+ std::vector<std::unique_ptr<GenericParam> > generic_params,
SelfParam self_param, std::vector<FunctionParam> function_params,
std::unique_ptr<Type> return_type, WhereClause where_clause,
std::unique_ptr<BlockExpr> function_body, Visibility vis,
- std::vector<Attribute> outer_attrs, Location locus = Location ())
+ std::vector<Attribute> outer_attrs, Location locus)
: outer_attrs (std::move (outer_attrs)), vis (std::move (vis)),
qualifiers (std::move (qualifiers)),
method_name (std::move (method_name)),
@@ -646,8 +738,8 @@ public:
self_param (std::move (self_param)),
function_params (std::move (function_params)),
return_type (std::move (return_type)),
- where_clause (std::move (where_clause)), expr (std::move (function_body)),
- locus (locus)
+ where_clause (std::move (where_clause)),
+ function_body (std::move (function_body)), locus (locus)
{}
// TODO: add constructor with less fields
@@ -657,10 +749,16 @@ public:
: outer_attrs (other.outer_attrs), vis (other.vis),
qualifiers (other.qualifiers), method_name (other.method_name),
self_param (other.self_param), function_params (other.function_params),
- return_type (other.return_type->clone_type ()),
- where_clause (other.where_clause), expr (other.expr->clone_block_expr ()),
- locus (other.locus)
+ where_clause (other.where_clause), locus (other.locus)
{
+ // guard to prevent null dereference (always required)
+ if (other.return_type != nullptr)
+ return_type = other.return_type->clone_type ();
+
+ // guard to prevent null dereference (only required if error state)
+ if (other.function_body != nullptr)
+ function_body = other.function_body->clone_block_expr ();
+
generic_params.reserve (other.generic_params.size ());
for (const auto &e : other.generic_params)
generic_params.push_back (e->clone_generic_param ());
@@ -675,11 +773,21 @@ public:
qualifiers = other.qualifiers;
self_param = other.self_param;
function_params = other.function_params;
- return_type = other.return_type->clone_type ();
where_clause = other.where_clause;
- expr = other.expr->clone_block_expr ();
locus = other.locus;
+ // guard to prevent null dereference (always required)
+ if (other.return_type != nullptr)
+ return_type = other.return_type->clone_type ();
+ else
+ return_type = nullptr;
+
+ // guard to prevent null dereference (only required if error state)
+ if (other.function_body != nullptr)
+ function_body = other.function_body->clone_block_expr ();
+ else
+ function_body = nullptr;
+
generic_params.reserve (other.generic_params.size ());
for (const auto &e : other.generic_params)
generic_params.push_back (e->clone_generic_param ());
@@ -695,6 +803,56 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Invalid if block is null, so base stripping on that.
+ void mark_for_strip () override { function_body = nullptr; }
+ bool is_marked_for_strip () const override
+ {
+ return function_body == nullptr;
+ }
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
+ const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+
+ std::vector<FunctionParam> &get_function_params () { return function_params; }
+ const std::vector<FunctionParam> &get_function_params () const
+ {
+ return function_params;
+ }
+
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params ()
+ {
+ return generic_params;
+ }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const
+ {
+ return generic_params;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<BlockExpr> &get_definition ()
+ {
+ rust_assert (function_body != nullptr);
+ return function_body;
+ }
+
+ SelfParam &get_self_param () { return self_param; }
+ const SelfParam &get_self_param () const { return self_param; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_return_type ()
+ {
+ rust_assert (has_return_type ());
+ return return_type;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause ()
+ {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -715,24 +873,25 @@ protected:
class VisItem : public Item
{
Visibility visibility;
+ std::vector<Attribute> outer_attrs;
protected:
// Visibility constructor
VisItem (Visibility visibility,
std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
- : Item (std::move (outer_attrs)), visibility (std::move (visibility))
+ : visibility (std::move (visibility)), outer_attrs (std::move (outer_attrs))
{}
// Visibility copy constructor
- VisItem (VisItem const &other) : Item (other), visibility (other.visibility)
+ VisItem (VisItem const &other)
+ : visibility (other.visibility), outer_attrs (other.outer_attrs)
{}
// Overload assignment operator to clone
VisItem &operator= (VisItem const &other)
{
- Item::operator= (other);
visibility = other.visibility;
- // outer_attrs = other.outer_attrs;
+ outer_attrs = other.outer_attrs;
return *this;
}
@@ -747,6 +906,13 @@ public:
bool has_visibility () const { return !visibility.is_error (); }
std::string as_string () const override;
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ Visibility &get_vis () { return visibility; }
+ const Visibility &get_vis () const { return visibility; }
+
+ std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
+ const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
};
// Rust module item - abstract base class
@@ -767,6 +933,10 @@ public:
std::string as_string () const override;
Location get_locus () const { return locus; }
+
+ // Invalid if name is empty, so base stripping on that.
+ void mark_for_strip () override { module_name = ""; }
+ bool is_marked_for_strip () const override { return module_name.empty (); }
};
// Module with a body, defined in file
@@ -775,7 +945,7 @@ class ModuleBodied : public Module
// bool has_inner_attrs;
std::vector<Attribute> inner_attrs;
// bool has_items;
- std::vector<std::unique_ptr<Item>> items;
+ std::vector<std::unique_ptr<Item> > items;
public:
std::string as_string () const override;
@@ -788,8 +958,8 @@ public:
// Full constructor
ModuleBodied (Identifier name, Location locus,
- std::vector<std::unique_ptr<Item>> items
- = std::vector<std::unique_ptr<Item>> (),
+ std::vector<std::unique_ptr<Item> > items
+ = std::vector<std::unique_ptr<Item> > (),
Visibility visibility = Visibility::create_error (),
std::vector<Attribute> inner_attrs = std::vector<Attribute> (),
std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
@@ -830,6 +1000,16 @@ public:
* the module. */
void add_crate_name (std::vector<std::string> &names) const override;
+ // TODO: think of better way to do this - mutable getter seems dodgy
+ const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
+ std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
+
+ const std::vector<std::unique_ptr<Item> > &get_items () const
+ {
+ return items;
+ }
+ std::vector<std::unique_ptr<Item> > &get_items () { return items; }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -837,17 +1017,16 @@ protected:
{
return new ModuleBodied (*this);
}
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual ModuleBodied* clone_statement_impl() const override {
- return new ModuleBodied(*this);
- }*/
};
// Module without a body, loaded from external file
class ModuleNoBody : public Module
{
+ /* TODO: are modules loaded from file unique? As in, can you load the same
+ * file into two different other files? Because this may make the difference
+ * between simply replacing this with the module
+ * "definition" (as loaded from another file) vs this having to "reference" a
+ * module with body. */
public:
std::string as_string () const override;
@@ -867,12 +1046,6 @@ protected:
{
return new ModuleNoBody (*this);
}
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual ModuleNoBody* clone_statement_impl() const override {
- return new ModuleNoBody(*this);
- }*/
};
// Rust extern crate declaration AST node
@@ -920,6 +1093,13 @@ public:
names.push_back (referenced_crate);
}
+ // Invalid if crate name is empty, so base stripping on that.
+ void mark_for_strip () override { referenced_crate = ""; }
+ bool is_marked_for_strip () const override
+ {
+ return referenced_crate.empty ();
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -927,12 +1107,6 @@ protected:
{
return new ExternCrate (*this);
}
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual ExternCrate* clone_statement_impl() const override {
- return new ExternCrate(*this);
- }*/
};
// The path-ish thing referred to in a use declaration - abstract base class
@@ -985,7 +1159,7 @@ public:
{
// compiler implementation error if there is a path with a
// non-path-prefixed use tree glob
- gcc_assert (!has_path ());
+ rust_assert (!has_path ());
}
// TODO: do path-prefixed paths also have to have a path? If so, have an
// assert for that too.
@@ -1025,11 +1199,11 @@ private:
PathType path_type;
SimplePath path;
- std::vector<std::unique_ptr<UseTree>> trees;
+ std::vector<std::unique_ptr<UseTree> > trees;
public:
UseTreeList (PathType path_type, SimplePath path,
- std::vector<std::unique_ptr<UseTree>> trees, Location locus)
+ std::vector<std::unique_ptr<UseTree> > trees, Location locus)
: UseTree (locus), path_type (path_type), path (std::move (path)),
trees (std::move (trees))
{
@@ -1037,7 +1211,7 @@ public:
{
// compiler implementation error if there is a path with a
// non-path-prefixed use tree glob
- gcc_assert (!has_path ());
+ rust_assert (!has_path ());
}
// TODO: do path-prefixed paths also have to have a path? If so, have an
// assert for that too.
@@ -1153,19 +1327,27 @@ public:
// Copy constructor with clone
UseDeclaration (UseDeclaration const &other)
- : VisItem (other), use_tree (other.use_tree->clone_use_tree ()),
- locus (other.locus)
- {}
+ : VisItem (other), locus (other.locus)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.use_tree != nullptr)
+ use_tree = other.use_tree->clone_use_tree ();
+ }
// Overloaded assignment operator to clone
UseDeclaration &operator= (UseDeclaration const &other)
{
VisItem::operator= (other);
- use_tree = other.use_tree->clone_use_tree ();
// visibility = other.visibility->clone_visibility();
// outer_attrs = other.outer_attrs;
locus = other.locus;
+ // guard to prevent null dereference (only required if error state)
+ if (other.use_tree != nullptr)
+ use_tree = other.use_tree->clone_use_tree ();
+ else
+ use_tree = nullptr;
+
return *this;
}
@@ -1177,6 +1359,10 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Invalid if use tree is null, so base stripping on that.
+ void mark_for_strip () override { use_tree = nullptr; }
+ bool is_marked_for_strip () const override { return use_tree == nullptr; }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -1184,12 +1370,6 @@ protected:
{
return new UseDeclaration (*this);
}
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual UseDeclaration* clone_statement_impl() const override {
- return new UseDeclaration(*this);
- }*/
};
// Parameters used in a function - TODO inline?
@@ -1202,13 +1382,12 @@ class LetStmt;
// Rust function declaration AST node
class Function : public VisItem, public InherentImplItem, public TraitImplItem
{
-public:
FunctionQualifiers qualifiers;
Identifier function_name;
// bool has_generics;
// Generics generic_params;
- std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
+ std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined
// bool has_function_params;
// FunctionParams function_params;
@@ -1224,6 +1403,7 @@ public:
Location locus;
+public:
std::vector<LetStmt *> locals;
std::string as_string () const override;
@@ -1235,14 +1415,14 @@ public:
bool has_function_params () const { return !function_params.empty (); }
// Returns whether function has return type - if not, it is void.
- bool has_function_return_type () const { return return_type != nullptr; }
+ bool has_return_type () const { return return_type != nullptr; }
// Returns whether function has a where clause.
bool has_where_clause () const { return !where_clause.is_empty (); }
// Mega-constructor with all possible fields
Function (Identifier function_name, FunctionQualifiers qualifiers,
- std::vector<std::unique_ptr<GenericParam>> generic_params,
+ std::vector<std::unique_ptr<GenericParam> > generic_params,
std::vector<FunctionParam> function_params,
std::unique_ptr<Type> return_type, WhereClause where_clause,
std::unique_ptr<BlockExpr> function_body, Visibility vis,
@@ -1264,11 +1444,16 @@ public:
: VisItem (other), qualifiers (other.qualifiers),
function_name (other.function_name),
function_params (other.function_params),
- return_type (other.return_type->clone_type ()),
- where_clause (other.where_clause),
- function_body (other.function_body->clone_block_expr ()),
- locus (other.locus)
+ where_clause (other.where_clause), locus (other.locus)
{
+ // guard to prevent null dereference (always required)
+ if (other.return_type != nullptr)
+ return_type = other.return_type->clone_type ();
+
+ // guard to prevent null dereference (only required if error state)
+ if (other.function_body != nullptr)
+ function_body = other.function_body->clone_block_expr ();
+
generic_params.reserve (other.generic_params.size ());
for (const auto &e : other.generic_params)
generic_params.push_back (e->clone_generic_param ());
@@ -1280,15 +1465,24 @@ public:
VisItem::operator= (other);
function_name = other.function_name;
qualifiers = other.qualifiers;
- // generic_params = other.generic_params;
function_params = other.function_params;
- return_type = other.return_type->clone_type ();
where_clause = other.where_clause;
- function_body = other.function_body->clone_block_expr ();
// visibility = other.visibility->clone_visibility();
// outer_attrs = other.outer_attrs;
locus = other.locus;
+ // guard to prevent null dereference (always required)
+ if (other.return_type != nullptr)
+ return_type = other.return_type->clone_type ();
+ else
+ return_type = nullptr;
+
+ // guard to prevent null dereference (only required if error state)
+ if (other.function_body != nullptr)
+ function_body = other.function_body->clone_block_expr ();
+ else
+ function_body = nullptr;
+
generic_params.reserve (other.generic_params.size ());
for (const auto &e : other.generic_params)
generic_params.push_back (e->clone_generic_param ());
@@ -1304,6 +1498,54 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Invalid if block is null, so base stripping on that.
+ void mark_for_strip () override { function_body = nullptr; }
+ bool is_marked_for_strip () const override
+ {
+ return function_body == nullptr;
+ }
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<FunctionParam> &get_function_params () { return function_params; }
+ const std::vector<FunctionParam> &get_function_params () const
+ {
+ return function_params;
+ }
+
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params ()
+ {
+ return generic_params;
+ }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const
+ {
+ return generic_params;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<BlockExpr> &get_definition ()
+ {
+ rust_assert (function_body != nullptr);
+ return function_body;
+ }
+
+ FunctionQualifiers get_qualifiers () const { return qualifiers; }
+
+ Identifier get_function_name () const { return function_name; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause ()
+ {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_return_type ()
+ {
+ rust_assert (has_return_type ());
+ return return_type;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -1322,12 +1564,6 @@ protected:
{
return new Function (*this);
}
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual Function* clone_statement_impl() const override {
- return new Function(*this);
- }*/
};
// Rust type alias (i.e. typedef) AST node
@@ -1337,7 +1573,7 @@ class TypeAlias : public VisItem, public TraitImplItem
// bool has_generics;
// Generics generic_params;
- std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
+ std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined
// bool has_where_clause;
WhereClause where_clause;
@@ -1357,7 +1593,7 @@ public:
// Mega-constructor with all possible fields
TypeAlias (Identifier new_type_name,
- std::vector<std::unique_ptr<GenericParam>> generic_params,
+ std::vector<std::unique_ptr<GenericParam> > generic_params,
WhereClause where_clause, std::unique_ptr<Type> existing_type,
Visibility vis, std::vector<Attribute> outer_attrs, Location locus)
: VisItem (std::move (vis), std::move (outer_attrs)),
@@ -1370,9 +1606,12 @@ public:
// Copy constructor
TypeAlias (TypeAlias const &other)
: VisItem (other), new_type_name (other.new_type_name),
- where_clause (other.where_clause),
- existing_type (other.existing_type->clone_type ()), locus (other.locus)
+ where_clause (other.where_clause), locus (other.locus)
{
+ // guard to prevent null dereference (only required if error state)
+ if (other.existing_type != nullptr)
+ existing_type = other.existing_type->clone_type ();
+
generic_params.reserve (other.generic_params.size ());
for (const auto &e : other.generic_params)
generic_params.push_back (e->clone_generic_param ());
@@ -1383,13 +1622,17 @@ public:
{
VisItem::operator= (other);
new_type_name = other.new_type_name;
- // generic_params = other.generic_params;
where_clause = other.where_clause;
- existing_type = other.existing_type->clone_type ();
// visibility = other.visibility->clone_visibility();
// outer_attrs = other.outer_attrs;
locus = other.locus;
+ // guard to prevent null dereference (only required if error state)
+ if (other.existing_type != nullptr)
+ existing_type = other.existing_type->clone_type ();
+ else
+ existing_type = nullptr;
+
generic_params.reserve (other.generic_params.size ());
for (const auto &e : other.generic_params)
generic_params.push_back (e->clone_generic_param ());
@@ -1405,6 +1648,36 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Invalid if existing type is null, so base stripping on that.
+ void mark_for_strip () override { existing_type = nullptr; }
+ bool is_marked_for_strip () const override
+ {
+ return existing_type == nullptr;
+ }
+
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params ()
+ {
+ return generic_params;
+ }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const
+ {
+ return generic_params;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause ()
+ {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type_aliased ()
+ {
+ rust_assert (existing_type != nullptr);
+ return existing_type;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -1416,30 +1689,26 @@ protected:
{
return new TypeAlias (*this);
}
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual TypeAlias* clone_statement_impl() const override {
- return new TypeAlias(*this);
- }*/
};
// Rust base struct declaration AST node - abstract base class
class Struct : public VisItem
{
-public:
+protected:
// protected to enable access by derived classes - allows better as_string
Identifier struct_name;
// bool has_generics;
// Generics generic_params;
- std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
+ std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined
// bool has_where_clause;
WhereClause where_clause;
+private:
Location locus;
+public:
// Returns whether struct has generic parameters.
bool has_generics () const { return !generic_params.empty (); }
@@ -1448,9 +1717,31 @@ public:
Location get_locus () const { return locus; }
+ // Invalid if name is empty, so base stripping on that.
+ void mark_for_strip () override { struct_name = ""; }
+ bool is_marked_for_strip () const override { return struct_name.empty (); }
+
+ Identifier get_struct_name () const { return struct_name; }
+
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params ()
+ {
+ return generic_params;
+ }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const
+ {
+ return generic_params;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause ()
+ {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
+
protected:
Struct (Identifier struct_name,
- std::vector<std::unique_ptr<GenericParam>> generic_params,
+ std::vector<std::unique_ptr<GenericParam> > generic_params,
WhereClause where_clause, Visibility vis, Location locus,
std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
: VisItem (std::move (vis), std::move (outer_attrs)),
@@ -1492,7 +1783,7 @@ protected:
// A single field in a struct
struct StructField
{
-public:
+private:
// bool has_outer_attributes;
std::vector<Attribute> outer_attrs;
@@ -1504,6 +1795,7 @@ public:
// should this store location info?
+public:
// Returns whether struct field has any outer attributes.
bool has_outer_attributes () const { return !outer_attrs.empty (); }
@@ -1520,9 +1812,12 @@ public:
// Copy constructor
StructField (StructField const &other)
: outer_attrs (other.outer_attrs), visibility (other.visibility),
- field_name (other.field_name),
- field_type (other.field_type->clone_type ())
- {}
+ field_name (other.field_name)
+ {
+ // guard to prevent null dereference
+ if (other.field_type != nullptr)
+ field_type = other.field_type->clone_type ();
+ }
~StructField () = default;
@@ -1530,10 +1825,15 @@ public:
StructField &operator= (StructField const &other)
{
field_name = other.field_name;
- field_type = other.field_type->clone_type ();
visibility = other.visibility;
outer_attrs = other.outer_attrs;
+ // guard to prevent null dereference
+ if (other.field_type != nullptr)
+ field_type = other.field_type->clone_type ();
+ else
+ field_type = nullptr;
+
return *this;
}
@@ -1555,20 +1855,35 @@ public:
}
std::string as_string () const;
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
+ const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+
+ Identifier get_field_name () const { return field_name; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_field_type ()
+ {
+ rust_assert (field_type != nullptr);
+ return field_type;
+ }
+
+ Visibility get_visibility () const { return visibility; }
};
// Rust struct declaration with true struct type AST node
class StructStruct : public Struct
{
-public:
std::vector<StructField> fields;
bool is_unit;
+public:
std::string as_string () const override;
// Mega-constructor with all possible fields
StructStruct (std::vector<StructField> fields, Identifier struct_name,
- std::vector<std::unique_ptr<GenericParam>> generic_params,
+ std::vector<std::unique_ptr<GenericParam> > generic_params,
WhereClause where_clause, bool is_unit, Visibility vis,
std::vector<Attribute> outer_attrs, Location locus)
: Struct (std::move (struct_name), std::move (generic_params),
@@ -1579,7 +1894,7 @@ public:
// Unit struct constructor
StructStruct (Identifier struct_name,
- std::vector<std::unique_ptr<GenericParam>> generic_params,
+ std::vector<std::unique_ptr<GenericParam> > generic_params,
WhereClause where_clause, Visibility vis,
std::vector<Attribute> outer_attrs, Location locus)
: Struct (std::move (struct_name), std::move (generic_params),
@@ -1596,6 +1911,10 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<StructField> &get_fields () { return fields; }
+ const std::vector<StructField> &get_fields () const { return fields; }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -1603,12 +1922,6 @@ protected:
{
return new StructStruct (*this);
}
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual StructStruct* clone_statement_impl() const override {
- return new StructStruct(*this);
- }*/
};
// A single field in a tuple
@@ -1642,19 +1955,27 @@ public:
// Copy constructor with clone
TupleField (TupleField const &other)
- : outer_attrs (other.outer_attrs), visibility (other.visibility),
- field_type (other.field_type->clone_type ())
- {}
+ : outer_attrs (other.outer_attrs), visibility (other.visibility)
+ {
+ // guard to prevent null dereference (only required if error)
+ if (other.field_type != nullptr)
+ field_type = other.field_type->clone_type ();
+ }
~TupleField () = default;
// Overloaded assignment operator to clone
TupleField &operator= (TupleField const &other)
{
- field_type = other.field_type->clone_type ();
visibility = other.visibility;
outer_attrs = other.outer_attrs;
+ // guard to prevent null dereference (only required if error)
+ if (other.field_type != nullptr)
+ field_type = other.field_type->clone_type ();
+ else
+ field_type = nullptr;
+
return *this;
}
@@ -1672,6 +1993,17 @@ public:
}
std::string as_string () const;
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
+ const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_field_type ()
+ {
+ rust_assert (field_type != nullptr);
+ return field_type;
+ }
};
// Rust tuple declared using struct keyword AST node
@@ -1684,7 +2016,7 @@ public:
// Mega-constructor with all possible fields
TupleStruct (std::vector<TupleField> fields, Identifier struct_name,
- std::vector<std::unique_ptr<GenericParam>> generic_params,
+ std::vector<std::unique_ptr<GenericParam> > generic_params,
WhereClause where_clause, Visibility vis,
std::vector<Attribute> outer_attrs, Location locus)
: Struct (std::move (struct_name), std::move (generic_params),
@@ -1695,6 +2027,10 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<TupleField> &get_fields () { return fields; }
+ const std::vector<TupleField> &get_fields () const { return fields; }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -1702,12 +2038,6 @@ protected:
{
return new TupleStruct (*this);
}
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual TupleStruct* clone_statement_impl() const override {
- return new TupleStruct(*this);
- }*/
};
/* An item used in an "enum" tagged union - not abstract: base represents a
@@ -1744,6 +2074,14 @@ public:
// not pure virtual as not abstract
virtual void accept_vis (ASTVisitor &vis);
+ // Based on idea that name is never empty.
+ void mark_for_strip () { variant_name = ""; }
+ bool is_marked_for_strip () const { return variant_name.empty (); }
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
+ const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+
protected:
// Clone function implementation as (not pure) virtual method
virtual EnumItem *clone_enum_item_impl () const
@@ -1772,6 +2110,13 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<TupleField> &get_tuple_fields () { return tuple_fields; }
+ const std::vector<TupleField> &get_tuple_fields () const
+ {
+ return tuple_fields;
+ }
+
protected:
// Clone function implementation as (not pure) virtual method
EnumItemTuple *clone_enum_item_impl () const override
@@ -1801,6 +2146,13 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<StructField> &get_struct_fields () { return struct_fields; }
+ const std::vector<StructField> &get_struct_fields () const
+ {
+ return struct_fields;
+ }
+
protected:
// Clone function implementation as (not pure) virtual method
EnumItemStruct *clone_enum_item_impl () const override
@@ -1845,6 +2197,13 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_expr ()
+ {
+ rust_assert (expression != nullptr);
+ return expression;
+ }
+
protected:
// Clone function implementation as (not pure) virtual method
EnumItemDiscriminant *clone_enum_item_impl () const override
@@ -1860,12 +2219,12 @@ class Enum : public VisItem
// bool has_generics;
// Generics generic_params;
- std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
+ std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined
// bool has_where_clause;
WhereClause where_clause;
- std::vector<std::unique_ptr<EnumItem>> items;
+ std::vector<std::unique_ptr<EnumItem> > items;
Location locus;
@@ -1884,8 +2243,8 @@ public:
// Mega-constructor
Enum (Identifier enum_name, Visibility vis,
- std::vector<std::unique_ptr<GenericParam>> generic_params,
- WhereClause where_clause, std::vector<std::unique_ptr<EnumItem>> items,
+ std::vector<std::unique_ptr<GenericParam> > generic_params,
+ WhereClause where_clause, std::vector<std::unique_ptr<EnumItem> > items,
std::vector<Attribute> outer_attrs, Location locus)
: VisItem (std::move (vis), std::move (outer_attrs)),
enum_name (std::move (enum_name)),
@@ -1937,16 +2296,37 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Invalid if name is empty, so base stripping on that.
+ void mark_for_strip () override { enum_name = ""; }
+ bool is_marked_for_strip () const override { return enum_name.empty (); }
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<std::unique_ptr<EnumItem> > &get_variants () { return items; }
+ const std::vector<std::unique_ptr<EnumItem> > &get_variants () const
+ {
+ return items;
+ }
+
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params ()
+ {
+ return generic_params;
+ }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const
+ {
+ return generic_params;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause ()
+ {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
Enum *clone_item_impl () const override { return new Enum (*this); }
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual Enum* clone_statement_impl() const override {
- return new Enum(*this);
- }*/
};
// Rust untagged union used for C compat AST node
@@ -1956,7 +2336,7 @@ class Union : public VisItem
// bool has_generics;
// Generics generic_params;
- std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
+ std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined
// bool has_where_clause;
WhereClause where_clause;
@@ -1975,7 +2355,7 @@ public:
bool has_where_clause () const { return !where_clause.is_empty (); }
Union (Identifier union_name, Visibility vis,
- std::vector<std::unique_ptr<GenericParam>> generic_params,
+ std::vector<std::unique_ptr<GenericParam> > generic_params,
WhereClause where_clause, std::vector<StructField> variants,
std::vector<Attribute> outer_attrs, Location locus)
: VisItem (std::move (vis), std::move (outer_attrs)),
@@ -2020,16 +2400,34 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Invalid if name is empty, so base stripping on that.
+ void mark_for_strip () override { union_name = ""; }
+ bool is_marked_for_strip () const override { return union_name.empty (); }
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<StructField> &get_variants () { return variants; }
+ const std::vector<StructField> &get_variants () const { return variants; }
+
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params ()
+ {
+ return generic_params;
+ }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const
+ {
+ return generic_params;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause ()
+ {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
Union *clone_item_impl () const override { return new Union (*this); }
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual Union* clone_statement_impl() const override {
- return new Union(*this);
- }*/
};
/* "Constant item" AST node - used for constant, compile-time expressions
@@ -2041,7 +2439,7 @@ class ConstantItem : public VisItem,
// either has an identifier or "_" - maybe handle in identifier?
// bool identifier_is_underscore;
// if no identifier declared, identifier will be "_"
- Identifier identifier;
+ std::string identifier;
std::unique_ptr<Type> type;
std::unique_ptr<Expr> const_expr;
@@ -2051,7 +2449,7 @@ class ConstantItem : public VisItem,
public:
std::string as_string () const override;
- ConstantItem (Identifier ident, Visibility vis, std::unique_ptr<Type> type,
+ ConstantItem (std::string ident, Visibility vis, std::unique_ptr<Type> type,
std::unique_ptr<Expr> const_expr,
std::vector<Attribute> outer_attrs, Location locus)
: VisItem (std::move (vis), std::move (outer_attrs)),
@@ -2060,20 +2458,32 @@ public:
{}
ConstantItem (ConstantItem const &other)
- : VisItem (other), identifier (other.identifier),
- type (other.type->clone_type ()),
- const_expr (other.const_expr->clone_expr ()), locus (other.locus)
- {}
+ : VisItem (other), identifier (other.identifier), locus (other.locus)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.type != nullptr)
+ type = other.type->clone_type ();
+ if (other.const_expr != nullptr)
+ const_expr = other.const_expr->clone_expr ();
+ }
// Overload assignment operator to clone
ConstantItem &operator= (ConstantItem const &other)
{
VisItem::operator= (other);
identifier = other.identifier;
- type = other.type->clone_type ();
- const_expr = other.const_expr->clone_expr ();
locus = other.locus;
+ // guard to prevent null dereference (only required if error state)
+ if (other.type != nullptr)
+ type = other.type->clone_type ();
+ else
+ type = nullptr;
+ if (other.const_expr != nullptr)
+ const_expr = other.const_expr->clone_expr ();
+ else
+ const_expr = nullptr;
+
return *this;
}
@@ -2083,12 +2493,37 @@ public:
/* Returns whether constant item is an "unnamed" (wildcard underscore used
* as identifier) constant. */
- bool is_unnamed () const { return identifier == std::string ("_"); }
+ bool is_unnamed () const { return identifier == "_"; }
Location get_locus () const { return locus; }
void accept_vis (ASTVisitor &vis) override;
+ // Invalid if type or expression are null, so base stripping on that.
+ void mark_for_strip () override
+ {
+ type = nullptr;
+ const_expr = nullptr;
+ }
+ bool is_marked_for_strip () const override
+ {
+ return type == nullptr && const_expr == nullptr;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_expr ()
+ {
+ rust_assert (const_expr != nullptr);
+ return const_expr;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type ()
+ {
+ rust_assert (type != nullptr);
+ return type;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -2110,12 +2545,6 @@ protected:
{
return new ConstantItem (*this);
}
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual ConstantItem* clone_statement_impl() const override {
- return new ConstantItem(*this);
- }*/
};
/* Static item AST node - items within module scope with fixed storage
@@ -2142,9 +2571,14 @@ public:
// Copy constructor with clone
StaticItem (StaticItem const &other)
: VisItem (other), has_mut (other.has_mut), name (other.name),
- type (other.type->clone_type ()), expr (other.expr->clone_expr ()),
locus (other.locus)
- {}
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.type != nullptr)
+ type = other.type->clone_type ();
+ if (other.expr != nullptr)
+ expr = other.expr->clone_expr ();
+ }
// Overloaded assignment operator to clone
StaticItem &operator= (StaticItem const &other)
@@ -2152,10 +2586,18 @@ public:
VisItem::operator= (other);
name = other.name;
has_mut = other.has_mut;
- type = other.type->clone_type ();
- expr = other.expr->clone_expr ();
locus = other.locus;
+ // guard to prevent null dereference (only required if error state)
+ if (other.type != nullptr)
+ type = other.type->clone_type ();
+ else
+ type = nullptr;
+ if (other.expr != nullptr)
+ expr = other.expr->clone_expr ();
+ else
+ expr = nullptr;
+
return *this;
}
@@ -2167,6 +2609,31 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Invalid if type or expression are null, so base stripping on that.
+ void mark_for_strip () override
+ {
+ type = nullptr;
+ expr = nullptr;
+ }
+ bool is_marked_for_strip () const override
+ {
+ return type == nullptr && expr == nullptr;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_expr ()
+ {
+ rust_assert (expr != nullptr);
+ return expr;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type ()
+ {
+ rust_assert (type != nullptr);
+ return type;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -2174,12 +2641,6 @@ protected:
{
return new StaticItem (*this);
}
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual StaticItem* clone_statement_impl() const override {
- return new StaticItem(*this);
- }*/
};
// Function declaration in traits
@@ -2192,7 +2653,7 @@ private:
// bool has_generics;
// Generics generic_params;
- std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
+ std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined
// bool has_params;
// FunctionParams function_params;
@@ -2221,7 +2682,7 @@ public:
// Mega-constructor
TraitFunctionDecl (Identifier function_name, FunctionQualifiers qualifiers,
- std::vector<std::unique_ptr<GenericParam>> generic_params,
+ std::vector<std::unique_ptr<GenericParam> > generic_params,
std::vector<FunctionParam> function_params,
std::unique_ptr<Type> return_type,
WhereClause where_clause)
@@ -2236,10 +2697,12 @@ public:
// Copy constructor with clone
TraitFunctionDecl (TraitFunctionDecl const &other)
: qualifiers (other.qualifiers), function_name (other.function_name),
- function_params (other.function_params),
- return_type (other.return_type->clone_type ()),
- where_clause (other.where_clause)
+ function_params (other.function_params), where_clause (other.where_clause)
{
+ // guard to prevent nullptr dereference
+ if (other.return_type != nullptr)
+ return_type = other.return_type->clone_type ();
+
generic_params.reserve (other.generic_params.size ());
for (const auto &e : other.generic_params)
generic_params.push_back (e->clone_generic_param ());
@@ -2253,9 +2716,14 @@ public:
function_name = other.function_name;
qualifiers = other.qualifiers;
function_params = other.function_params;
- return_type = other.return_type->clone_type ();
where_clause = other.where_clause;
+ // guard to prevent nullptr dereference
+ if (other.return_type != nullptr)
+ return_type = other.return_type->clone_type ();
+ else
+ return_type = nullptr;
+
generic_params.reserve (other.generic_params.size ());
for (const auto &e : other.generic_params)
generic_params.push_back (e->clone_generic_param ());
@@ -2268,6 +2736,40 @@ public:
TraitFunctionDecl &operator= (TraitFunctionDecl &&other) = default;
std::string as_string () const;
+
+ // Invalid if function name is empty, so base stripping on that.
+ void mark_for_strip () { function_name = ""; }
+ bool is_marked_for_strip () const { return function_name.empty (); }
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<FunctionParam> &get_function_params () { return function_params; }
+ const std::vector<FunctionParam> &get_function_params () const
+ {
+ return function_params;
+ }
+
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params ()
+ {
+ return generic_params;
+ }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const
+ {
+ return generic_params;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_return_type ()
+ {
+ rust_assert (has_return_type ());
+ return return_type;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause ()
+ {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
};
// Actual trait item function declaration within traits
@@ -2292,6 +2794,7 @@ public:
TraitItemFunc (TraitItemFunc const &other)
: outer_attrs (other.outer_attrs), decl (other.decl), locus (other.locus)
{
+ // guard to prevent null dereference
if (other.block_expr != nullptr)
block_expr = other.block_expr->clone_block_expr ();
}
@@ -2303,8 +2806,12 @@ public:
outer_attrs = other.outer_attrs;
decl = other.decl;
locus = other.locus;
+
+ // guard to prevent null dereference
if (other.block_expr != nullptr)
block_expr = other.block_expr->clone_block_expr ();
+ else
+ block_expr = nullptr;
return *this;
}
@@ -2319,6 +2826,31 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Invalid if trait decl is empty, so base stripping on that.
+ void mark_for_strip () override { decl.mark_for_strip (); }
+ bool is_marked_for_strip () const override
+ {
+ return decl.is_marked_for_strip ();
+ }
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
+ const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<BlockExpr> &get_definition ()
+ {
+ rust_assert (has_definition ());
+ return block_expr;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ TraitFunctionDecl &get_trait_function_decl ()
+ {
+ // TODO: maybe only allow access if not marked for strip?
+ return decl;
+ }
+
protected:
// Clone function implementation as (not pure) virtual method
TraitItemFunc *clone_trait_item_impl () const override
@@ -2337,7 +2869,7 @@ private:
// bool has_generics;
// Generics generic_params;
- std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
+ std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined
SelfParam self_param;
@@ -2368,7 +2900,7 @@ public:
// Mega-constructor
TraitMethodDecl (Identifier function_name, FunctionQualifiers qualifiers,
- std::vector<std::unique_ptr<GenericParam>> generic_params,
+ std::vector<std::unique_ptr<GenericParam> > generic_params,
SelfParam self_param,
std::vector<FunctionParam> function_params,
std::unique_ptr<Type> return_type, WhereClause where_clause)
@@ -2385,9 +2917,12 @@ public:
TraitMethodDecl (TraitMethodDecl const &other)
: qualifiers (other.qualifiers), function_name (other.function_name),
self_param (other.self_param), function_params (other.function_params),
- return_type (other.return_type->clone_type ()),
where_clause (other.where_clause)
{
+ // guard to prevent nullptr dereference
+ if (other.return_type != nullptr)
+ return_type = other.return_type->clone_type ();
+
generic_params.reserve (other.generic_params.size ());
for (const auto &e : other.generic_params)
generic_params.push_back (e->clone_generic_param ());
@@ -2402,9 +2937,14 @@ public:
qualifiers = other.qualifiers;
self_param = other.self_param;
function_params = other.function_params;
- return_type = other.return_type->clone_type ();
where_clause = other.where_clause;
+ // guard to prevent nullptr dereference
+ if (other.return_type != nullptr)
+ return_type = other.return_type->clone_type ();
+ else
+ return_type = nullptr;
+
generic_params.reserve (other.generic_params.size ());
for (const auto &e : other.generic_params)
generic_params.push_back (e->clone_generic_param ());
@@ -2417,6 +2957,43 @@ public:
TraitMethodDecl &operator= (TraitMethodDecl &&other) = default;
std::string as_string () const;
+
+ // Invalid if method name is empty, so base stripping on that.
+ void mark_for_strip () { function_name = ""; }
+ bool is_marked_for_strip () const { return function_name.empty (); }
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<FunctionParam> &get_function_params () { return function_params; }
+ const std::vector<FunctionParam> &get_function_params () const
+ {
+ return function_params;
+ }
+
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params ()
+ {
+ return generic_params;
+ }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const
+ {
+ return generic_params;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_return_type ()
+ {
+ rust_assert (has_return_type ());
+ return return_type;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause ()
+ {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
+
+ SelfParam &get_self_param () { return self_param; }
+ const SelfParam &get_self_param () const { return self_param; }
};
// Actual trait item method declaration within traits
@@ -2439,9 +3016,12 @@ public:
// Copy constructor with clone
TraitItemMethod (TraitItemMethod const &other)
- : outer_attrs (other.outer_attrs), decl (other.decl),
- block_expr (other.block_expr->clone_block_expr ()), locus (other.locus)
- {}
+ : outer_attrs (other.outer_attrs), decl (other.decl), locus (other.locus)
+ {
+ // guard to prevent null dereference
+ if (other.block_expr != nullptr)
+ block_expr = other.block_expr->clone_block_expr ();
+ }
// Overloaded assignment operator to clone
TraitItemMethod &operator= (TraitItemMethod const &other)
@@ -2449,9 +3029,14 @@ public:
TraitItem::operator= (other);
outer_attrs = other.outer_attrs;
decl = other.decl;
- block_expr = other.block_expr->clone_block_expr ();
locus = other.locus;
+ // guard to prevent null dereference
+ if (other.block_expr != nullptr)
+ block_expr = other.block_expr->clone_block_expr ();
+ else
+ block_expr = nullptr;
+
return *this;
}
@@ -2465,6 +3050,31 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Invalid if trait decl is empty, so base stripping on that.
+ void mark_for_strip () override { decl.mark_for_strip (); }
+ bool is_marked_for_strip () const override
+ {
+ return decl.is_marked_for_strip ();
+ }
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
+ const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ TraitMethodDecl &get_trait_method_decl ()
+ {
+ // TODO: maybe only allow access if not marked for strip?
+ return decl;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<BlockExpr> &get_definition ()
+ {
+ rust_assert (has_definition ());
+ return block_expr;
+ }
+
protected:
// Clone function implementation as (not pure) virtual method
TraitItemMethod *clone_trait_item_impl () const override
@@ -2498,10 +3108,16 @@ public:
// Copy constructor with clones
TraitItemConst (TraitItemConst const &other)
- : outer_attrs (other.outer_attrs), name (other.name),
- type (other.type->clone_type ()), expr (other.expr->clone_expr ()),
- locus (other.locus)
- {}
+ : outer_attrs (other.outer_attrs), name (other.name), locus (other.locus)
+ {
+ // guard to prevent null dereference
+ if (other.expr != nullptr)
+ expr = other.expr->clone_expr ();
+
+ // guard to prevent null dereference (only for error state)
+ if (other.type != nullptr)
+ type = other.type->clone_type ();
+ }
// Overloaded assignment operator to clone
TraitItemConst &operator= (TraitItemConst const &other)
@@ -2509,10 +3125,20 @@ public:
TraitItem::operator= (other);
outer_attrs = other.outer_attrs;
name = other.name;
- type = other.type->clone_type ();
- expr = other.expr->clone_expr ();
locus = other.locus;
+ // guard to prevent null dereference
+ if (other.expr != nullptr)
+ expr = other.expr->clone_expr ();
+ else
+ expr = nullptr;
+
+ // guard to prevent null dereference (only for error state)
+ if (other.type != nullptr)
+ type = other.type->clone_type ();
+ else
+ type = nullptr;
+
return *this;
}
@@ -2526,6 +3152,28 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Invalid if type is null, so base stripping on that.
+ void mark_for_strip () override { type = nullptr; }
+ bool is_marked_for_strip () const override { return type == nullptr; }
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
+ const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_expr ()
+ {
+ rust_assert (expr != nullptr);
+ return expr;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type ()
+ {
+ rust_assert (type != nullptr);
+ return type;
+ }
+
protected:
// Clone function implementation as (not pure) virtual method
TraitItemConst *clone_trait_item_impl () const override
@@ -2543,7 +3191,7 @@ class TraitItemType : public TraitItem
// bool has_type_param_bounds;
// TypeParamBounds type_param_bounds;
- std::vector<std::unique_ptr<TypeParamBound>>
+ std::vector<std::unique_ptr<TypeParamBound> >
type_param_bounds; // inlined form
Location locus;
@@ -2554,7 +3202,7 @@ public:
TraitItemType (
Identifier name,
- std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
+ std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds,
std::vector<Attribute> outer_attrs, Location locus)
: outer_attrs (std::move (outer_attrs)), name (std::move (name)),
type_param_bounds (std::move (type_param_bounds)), locus (locus)
@@ -2594,6 +3242,25 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Invalid if name is empty, so base stripping on that.
+ void mark_for_strip () override { name = ""; }
+ bool is_marked_for_strip () const override { return name.empty (); }
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
+ const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+
+ // TODO: mutable getter seems kinda dodgy
+ std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds ()
+ {
+ return type_param_bounds;
+ }
+ const std::vector<std::unique_ptr<TypeParamBound> > &
+ get_type_param_bounds () const
+ {
+ return type_param_bounds;
+ }
+
protected:
// Clone function implementation as (not pure) virtual method
TraitItemType *clone_trait_item_impl () const override
@@ -2606,23 +3273,24 @@ protected:
class Trait : public VisItem
{
bool has_unsafe;
-
Identifier name;
// bool has_generics;
// Generics generic_params;
- std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
+ std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined
// bool has_type_param_bounds;
// TypeParamBounds type_param_bounds;
- std::vector<std::unique_ptr<TypeParamBound>>
+ std::vector<std::unique_ptr<TypeParamBound> >
type_param_bounds; // inlined form
// bool has_where_clause;
WhereClause where_clause;
+ std::vector<Attribute> inner_attrs;
+
// bool has_trait_items;
- std::vector<std::unique_ptr<TraitItem>> trait_items;
+ std::vector<std::unique_ptr<TraitItem> > trait_items;
Location locus;
@@ -2641,25 +3309,31 @@ public:
// Returns whether trait has trait items.
bool has_trait_items () const { return !trait_items.empty (); }
+ // Returns whether trait has inner attributes.
+ bool has_inner_attrs () const { return !inner_attrs.empty (); }
+
// Mega-constructor
Trait (Identifier name, bool is_unsafe,
- std::vector<std::unique_ptr<GenericParam>> generic_params,
- std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
+ std::vector<std::unique_ptr<GenericParam> > generic_params,
+ std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds,
WhereClause where_clause,
- std::vector<std::unique_ptr<TraitItem>> trait_items, Visibility vis,
- std::vector<Attribute> outer_attrs, Location locus)
+ std::vector<std::unique_ptr<TraitItem> > trait_items, Visibility vis,
+ std::vector<Attribute> outer_attrs, std::vector<Attribute> inner_attrs,
+ Location locus)
: VisItem (std::move (vis), std::move (outer_attrs)),
has_unsafe (is_unsafe), name (std::move (name)),
generic_params (std::move (generic_params)),
type_param_bounds (std::move (type_param_bounds)),
where_clause (std::move (where_clause)),
+ inner_attrs (std::move (inner_attrs)),
trait_items (std::move (trait_items)), locus (locus)
{}
// Copy constructor with vector clone
Trait (Trait const &other)
: VisItem (other), has_unsafe (other.has_unsafe), name (other.name),
- where_clause (other.where_clause), locus (other.locus)
+ where_clause (other.where_clause), inner_attrs (other.inner_attrs),
+ locus (other.locus)
{
generic_params.reserve (other.generic_params.size ());
for (const auto &e : other.generic_params)
@@ -2681,6 +3355,7 @@ public:
name = other.name;
has_unsafe = other.has_unsafe;
where_clause = other.where_clause;
+ inner_attrs = other.inner_attrs;
locus = other.locus;
generic_params.reserve (other.generic_params.size ());
@@ -2706,16 +3381,53 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Invalid if trait name is empty, so base stripping on that.
+ void mark_for_strip () override { name = ""; }
+ bool is_marked_for_strip () const override { return name.empty (); }
+
+ // TODO: think of better way to do this
+ const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
+ std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
+
+ const std::vector<std::unique_ptr<TraitItem> > &get_trait_items () const
+ {
+ return trait_items;
+ }
+ std::vector<std::unique_ptr<TraitItem> > &get_trait_items ()
+ {
+ return trait_items;
+ }
+
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params ()
+ {
+ return generic_params;
+ }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const
+ {
+ return generic_params;
+ }
+
+ std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds ()
+ {
+ return type_param_bounds;
+ }
+ const std::vector<std::unique_ptr<TypeParamBound> > &
+ get_type_param_bounds () const
+ {
+ return type_param_bounds;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause ()
+ {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
Trait *clone_item_impl () const override { return new Trait (*this); }
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual Trait* clone_statement_impl() const override {
- return new Trait(*this);
- }*/
};
// Implementation item declaration AST node - abstract base class
@@ -2725,7 +3437,7 @@ class Impl : public VisItem
protected:
// bool has_generics;
// Generics generic_params;
- std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
+ std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined
std::unique_ptr<Type> trait_type;
@@ -2751,9 +3463,40 @@ public:
Location get_locus () const { return locus; }
+ // Invalid if trait type is null, so base stripping on that.
+ void mark_for_strip () override { trait_type = nullptr; }
+ bool is_marked_for_strip () const override { return trait_type == nullptr; }
+
+ // TODO: think of better way to do this
+ const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
+ std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
+
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params ()
+ {
+ return generic_params;
+ }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const
+ {
+ return generic_params;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause ()
+ {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type ()
+ {
+ rust_assert (trait_type != nullptr);
+ return trait_type;
+ }
+
protected:
// Mega-constructor
- Impl (std::vector<std::unique_ptr<GenericParam>> generic_params,
+ Impl (std::vector<std::unique_ptr<GenericParam> > generic_params,
std::unique_ptr<Type> trait_type, WhereClause where_clause,
Visibility vis, std::vector<Attribute> inner_attrs,
std::vector<Attribute> outer_attrs, Location locus)
@@ -2766,10 +3509,13 @@ protected:
// Copy constructor
Impl (Impl const &other)
- : VisItem (other), trait_type (other.trait_type->clone_type ()),
- where_clause (other.where_clause), inner_attrs (other.inner_attrs),
- locus (other.locus)
+ : VisItem (other), where_clause (other.where_clause),
+ inner_attrs (other.inner_attrs), locus (other.locus)
{
+ // guard to prevent null dereference (only required if error state)
+ if (other.trait_type != nullptr)
+ trait_type = other.trait_type->clone_type ();
+
generic_params.reserve (other.generic_params.size ());
for (const auto &e : other.generic_params)
generic_params.push_back (e->clone_generic_param ());
@@ -2779,11 +3525,16 @@ protected:
Impl &operator= (Impl const &other)
{
VisItem::operator= (other);
- trait_type = other.trait_type->clone_type ();
where_clause = other.where_clause;
inner_attrs = other.inner_attrs;
locus = other.locus;
+ // guard to prevent null dereference (only required if error state)
+ if (other.trait_type != nullptr)
+ trait_type = other.trait_type->clone_type ();
+ else
+ trait_type = nullptr;
+
generic_params.reserve (other.generic_params.size ());
for (const auto &e : other.generic_params)
generic_params.push_back (e->clone_generic_param ());
@@ -2800,7 +3551,7 @@ protected:
class InherentImpl : public Impl
{
// bool has_impl_items;
- std::vector<std::unique_ptr<InherentImplItem>> impl_items;
+ std::vector<std::unique_ptr<InherentImplItem> > impl_items;
public:
std::string as_string () const override;
@@ -2809,8 +3560,8 @@ public:
bool has_impl_items () const { return !impl_items.empty (); }
// Mega-constructor
- InherentImpl (std::vector<std::unique_ptr<InherentImplItem>> impl_items,
- std::vector<std::unique_ptr<GenericParam>> generic_params,
+ InherentImpl (std::vector<std::unique_ptr<InherentImplItem> > impl_items,
+ std::vector<std::unique_ptr<GenericParam> > generic_params,
std::unique_ptr<Type> trait_type, WhereClause where_clause,
Visibility vis, std::vector<Attribute> inner_attrs,
std::vector<Attribute> outer_attrs, Location locus)
@@ -2846,6 +3597,16 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: think of better way to do this
+ const std::vector<std::unique_ptr<InherentImplItem> > &get_impl_items () const
+ {
+ return impl_items;
+ }
+ std::vector<std::unique_ptr<InherentImplItem> > &get_impl_items ()
+ {
+ return impl_items;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -2853,12 +3614,6 @@ protected:
{
return new InherentImpl (*this);
}
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual InherentImpl* clone_statement_impl() const override {
- return new InherentImpl(*this);
- }*/
};
// The "impl footrait for foo" impl block declaration AST node
@@ -2869,7 +3624,7 @@ class TraitImpl : public Impl
TypePath trait_path;
// bool has_impl_items;
- std::vector<std::unique_ptr<TraitImplItem>> impl_items;
+ std::vector<std::unique_ptr<TraitImplItem> > impl_items;
public:
std::string as_string () const override;
@@ -2879,8 +3634,8 @@ public:
// Mega-constructor
TraitImpl (TypePath trait_path, bool is_unsafe, bool has_exclam,
- std::vector<std::unique_ptr<TraitImplItem>> impl_items,
- std::vector<std::unique_ptr<GenericParam>> generic_params,
+ std::vector<std::unique_ptr<TraitImplItem> > impl_items,
+ std::vector<std::unique_ptr<GenericParam> > generic_params,
std::unique_ptr<Type> trait_type, WhereClause where_clause,
Visibility vis, std::vector<Attribute> inner_attrs,
std::vector<Attribute> outer_attrs, Location locus)
@@ -2924,18 +3679,30 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: think of better way to do this
+ const std::vector<std::unique_ptr<TraitImplItem> > &get_impl_items () const
+ {
+ return impl_items;
+ }
+ std::vector<std::unique_ptr<TraitImplItem> > &get_impl_items ()
+ {
+ return impl_items;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ TypePath &get_trait_path ()
+ {
+ // TODO: assert that trait path is not empty?
+ return trait_path;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
TraitImpl *clone_item_impl () const override { return new TraitImpl (*this); }
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual TraitImpl* clone_statement_impl() const override {
- return new TraitImpl(*this);
- }*/
};
+#if 0
// Abstract base class for an item used inside an extern block
class ExternalItem
{
@@ -2951,6 +3718,10 @@ class ExternalItem
public:
virtual ~ExternalItem () {}
+ /* TODO: spec syntax rules state that "MacroInvocationSemi" can be used as
+ * ExternalItem, but text body isn't so clear. Adding MacroInvocationSemi
+ * support would require a lot of refactoring. */
+
// Returns whether item has outer attributes.
bool has_outer_attrs () const { return !outer_attrs.empty (); }
@@ -2969,6 +3740,11 @@ public:
virtual void accept_vis (ASTVisitor &vis) = 0;
+ // TODO: make virtual? Would be more flexible.
+ // Based on idea that name should never be empty.
+ void mark_for_strip () { item_name = ""; };
+ bool is_marked_for_strip () const { return item_name.empty (); };
+
protected:
ExternalItem (Identifier item_name, Visibility vis,
std::vector<Attribute> outer_attrs, Location locus)
@@ -3003,10 +3779,20 @@ protected:
// possibly make this public if required
std::string get_item_name () const { return item_name; }
};
+#endif
// A static item used in an extern block
class ExternalStaticItem : public ExternalItem
{
+ // bool has_outer_attrs;
+ std::vector<Attribute> outer_attrs;
+
+ // bool has_visibility;
+ Visibility visibility;
+
+ Identifier item_name;
+ Location locus;
+
bool has_mut;
std::unique_ptr<Type> item_type;
@@ -3014,24 +3800,36 @@ public:
ExternalStaticItem (Identifier item_name, std::unique_ptr<Type> item_type,
bool is_mut, Visibility vis,
std::vector<Attribute> outer_attrs, Location locus)
- : ExternalItem (std::move (item_name), std::move (vis),
- std::move (outer_attrs), locus),
- has_mut (is_mut), item_type (std::move (item_type))
+ : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)),
+ item_name (std::move (item_name)), locus (locus), has_mut (is_mut),
+ item_type (std::move (item_type))
{}
// Copy constructor
ExternalStaticItem (ExternalStaticItem const &other)
- : ExternalItem (other), has_mut (other.has_mut),
- item_type (other.item_type->clone_type ())
- {}
+ : outer_attrs (other.outer_attrs), visibility (other.visibility),
+ item_name (other.item_name), locus (other.locus), has_mut (other.has_mut)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.item_type != nullptr)
+ item_type = other.item_type->clone_type ();
+ }
// Overloaded assignment operator to clone
ExternalStaticItem &operator= (ExternalStaticItem const &other)
{
- ExternalItem::operator= (other);
- item_type = other.item_type->clone_type ();
+ outer_attrs = other.outer_attrs;
+ visibility = other.visibility;
+ item_name = other.item_name;
+ locus = other.locus;
has_mut = other.has_mut;
+ // guard to prevent null dereference (only required if error state)
+ if (other.item_type != nullptr)
+ item_type = other.item_type->clone_type ();
+ else
+ item_type = nullptr;
+
return *this;
}
@@ -3043,6 +3841,29 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Returns whether item has outer attributes.
+ bool has_outer_attrs () const { return !outer_attrs.empty (); }
+
+ // Returns whether item has non-default visibility.
+ bool has_visibility () const { return !visibility.is_error (); }
+
+ Location get_locus () const { return locus; }
+
+ // Based on idea that type should never be null.
+ void mark_for_strip () override { item_type = nullptr; };
+ bool is_marked_for_strip () const override { return item_type == nullptr; };
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
+ const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type ()
+ {
+ rust_assert (item_type != nullptr);
+ return item_type;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -3057,17 +3878,22 @@ struct NamedFunctionParam
{
private:
// bool has_name; // otherwise is _
- Identifier name; // TODO: handle wildcard in identifier?
+ std::string name;
std::unique_ptr<Type> param_type;
// TODO: should this store location data?
+ // seemingly new since writing this node
+ std::vector<Attribute> outer_attrs;
+
public:
- // Returns whether the named function parameter has a name (i.e. name is not
- // '_').
+ /* Returns whether the named function parameter has a name (i.e. name is not
+ * '_'). */
bool has_name () const { return name != "_"; }
+ bool has_outer_attrs () const { return !outer_attrs.empty (); }
+
// Returns whether the named function parameter is in an error state.
bool is_error () const
{
@@ -3078,17 +3904,23 @@ public:
// Creates an error state named function parameter.
static NamedFunctionParam create_error ()
{
- return NamedFunctionParam ("", nullptr);
+ return NamedFunctionParam ("", nullptr, {});
}
- NamedFunctionParam (Identifier name, std::unique_ptr<Type> param_type)
- : name (std::move (name)), param_type (std::move (param_type))
+ NamedFunctionParam (std::string name, std::unique_ptr<Type> param_type,
+ std::vector<Attribute> outer_attrs)
+ : name (std::move (name)), param_type (std::move (param_type)),
+ outer_attrs (std::move (outer_attrs))
{}
// Copy constructor
NamedFunctionParam (NamedFunctionParam const &other)
- : name (other.name), param_type (other.param_type->clone_type ())
- {}
+ : name (other.name), outer_attrs (other.outer_attrs)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.param_type != nullptr)
+ param_type = other.param_type->clone_type ();
+ }
~NamedFunctionParam () = default;
@@ -3096,8 +3928,14 @@ public:
NamedFunctionParam &operator= (NamedFunctionParam const &other)
{
name = other.name;
- param_type = other.param_type->clone_type ();
// has_name = other.has_name;
+ outer_attrs = other.outer_attrs;
+
+ // guard to prevent null dereference (only required if error state)
+ if (other.param_type != nullptr)
+ param_type = other.param_type->clone_type ();
+ else
+ param_type = nullptr;
return *this;
}
@@ -3107,14 +3945,38 @@ public:
NamedFunctionParam &operator= (NamedFunctionParam &&other) = default;
std::string as_string () const;
+
+ // Based on idea that nane should never be empty.
+ void mark_for_strip () { param_type = nullptr; };
+ bool is_marked_for_strip () const { return is_error (); };
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
+ const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type ()
+ {
+ rust_assert (param_type != nullptr);
+ return param_type;
+ }
};
// A function item used in an extern block
class ExternalFunctionItem : public ExternalItem
{
+ // bool has_outer_attrs;
+ std::vector<Attribute> outer_attrs;
+
+ // bool has_visibility;
+ Visibility visibility;
+
+ Identifier item_name;
+ Location locus;
+
// bool has_generics;
// Generics generic_params;
- std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
+ std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined
// bool has_return_type;
// FunctionReturnType return_type;
@@ -3125,6 +3987,7 @@ class ExternalFunctionItem : public ExternalItem
std::vector<NamedFunctionParam> function_params;
bool has_variadics;
+ std::vector<Attribute> variadic_outer_attrs;
public:
// Returns whether item has generic parameters.
@@ -3136,28 +3999,56 @@ public:
// Returns whether item has a where clause.
bool has_where_clause () const { return !where_clause.is_empty (); }
+ // Returns whether item has outer attributes.
+ bool has_outer_attrs () const { return !outer_attrs.empty (); }
+
+ // Returns whether item has non-default visibility.
+ bool has_visibility () const { return !visibility.is_error (); }
+
+ // Returns whether item has variadic parameters.
+ bool is_variadic () const { return has_variadics; }
+
+ // Returns whether item has outer attributes on its variadic parameters.
+ bool has_variadic_outer_attrs () const
+ {
+ return !variadic_outer_attrs.empty ();
+ }
+
+ Location get_locus () const { return locus; }
+
ExternalFunctionItem (
Identifier item_name,
- std::vector<std::unique_ptr<GenericParam>> generic_params,
+ std::vector<std::unique_ptr<GenericParam> > generic_params,
std::unique_ptr<Type> return_type, WhereClause where_clause,
std::vector<NamedFunctionParam> function_params, bool has_variadics,
- Visibility vis, std::vector<Attribute> outer_attrs, Location locus)
- : ExternalItem (std::move (item_name), std::move (vis),
- std::move (outer_attrs), locus),
+ std::vector<Attribute> variadic_outer_attrs, Visibility vis,
+ std::vector<Attribute> outer_attrs, Location locus)
+ : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)),
+ item_name (std::move (item_name)), locus (locus),
generic_params (std::move (generic_params)),
return_type (std::move (return_type)),
where_clause (std::move (where_clause)),
function_params (std::move (function_params)),
- has_variadics (has_variadics)
- {}
+ has_variadics (has_variadics),
+ variadic_outer_attrs (std::move (variadic_outer_attrs))
+ {
+ // TODO: assert that if has variadic outer attrs, then has_variadics is
+ // true?
+ }
// Copy constructor with clone
ExternalFunctionItem (ExternalFunctionItem const &other)
- : ExternalItem (other), return_type (other.return_type->clone_type ()),
+ : outer_attrs (other.outer_attrs), visibility (other.visibility),
+ item_name (other.item_name), locus (other.locus),
where_clause (other.where_clause),
function_params (other.function_params),
- has_variadics (other.has_variadics)
+ has_variadics (other.has_variadics),
+ variadic_outer_attrs (other.variadic_outer_attrs)
{
+ // guard to prevent null pointer dereference
+ if (other.return_type != nullptr)
+ return_type = other.return_type->clone_type ();
+
generic_params.reserve (other.generic_params.size ());
for (const auto &e : other.generic_params)
generic_params.push_back (e->clone_generic_param ());
@@ -3166,11 +4057,20 @@ public:
// Overloaded assignment operator with clone
ExternalFunctionItem &operator= (ExternalFunctionItem const &other)
{
- ExternalItem::operator= (other);
- return_type = other.return_type->clone_type ();
+ outer_attrs = other.outer_attrs;
+ visibility = other.visibility;
+ item_name = other.item_name;
+ locus = other.locus;
where_clause = other.where_clause;
function_params = other.function_params;
has_variadics = other.has_variadics;
+ variadic_outer_attrs = other.variadic_outer_attrs;
+
+ // guard to prevent null pointer dereference
+ if (other.return_type != nullptr)
+ return_type = other.return_type->clone_type ();
+ else
+ return_type = nullptr;
generic_params.reserve (other.generic_params.size ());
for (const auto &e : other.generic_params)
@@ -3187,6 +4087,46 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Based on idea that nane should never be empty.
+ void mark_for_strip () override { item_name = ""; };
+ bool is_marked_for_strip () const override { return item_name.empty (); };
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
+ const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+
+ std::vector<NamedFunctionParam> &get_function_params ()
+ {
+ return function_params;
+ }
+ const std::vector<NamedFunctionParam> &get_function_params () const
+ {
+ return function_params;
+ }
+
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params ()
+ {
+ return generic_params;
+ }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const
+ {
+ return generic_params;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause ()
+ {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_return_type ()
+ {
+ rust_assert (has_return_type ());
+ return return_type;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -3206,10 +4146,13 @@ class ExternBlock : public VisItem
std::vector<Attribute> inner_attrs;
// bool has_extern_items;
- std::vector<std::unique_ptr<ExternalItem>> extern_items;
+ std::vector<std::unique_ptr<ExternalItem> > extern_items;
Location locus;
+ // TODO: find another way to store this to save memory?
+ bool marked_for_strip = false;
+
public:
std::string as_string () const override;
@@ -3223,7 +4166,7 @@ public:
bool has_abi () const { return !abi.empty (); }
ExternBlock (std::string abi,
- std::vector<std::unique_ptr<ExternalItem>> extern_items,
+ std::vector<std::unique_ptr<ExternalItem> > extern_items,
Visibility vis, std::vector<Attribute> inner_attrs,
std::vector<Attribute> outer_attrs, Location locus)
: VisItem (std::move (vis), std::move (outer_attrs)), abi (std::move (abi)),
@@ -3234,7 +4177,7 @@ public:
// Copy constructor with vector clone
ExternBlock (ExternBlock const &other)
: VisItem (other), abi (other.abi), inner_attrs (other.inner_attrs),
- locus (other.locus)
+ locus (other.locus), marked_for_strip (other.marked_for_strip)
{
extern_items.reserve (other.extern_items.size ());
for (const auto &e : other.extern_items)
@@ -3248,6 +4191,7 @@ public:
abi = other.abi;
inner_attrs = other.inner_attrs;
locus = other.locus;
+ marked_for_strip = other.marked_for_strip;
extern_items.reserve (other.extern_items.size ());
for (const auto &e : other.extern_items)
@@ -3264,6 +4208,24 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Can't think of any invalid invariants, so store boolean.
+ void mark_for_strip () override { marked_for_strip = true; }
+ bool is_marked_for_strip () const override { return marked_for_strip; }
+
+ // TODO: think of better way to do this
+ const std::vector<std::unique_ptr<ExternalItem> > &get_extern_items () const
+ {
+ return extern_items;
+ }
+ std::vector<std::unique_ptr<ExternalItem> > &get_extern_items ()
+ {
+ return extern_items;
+ }
+
+ // TODO: think of better way to do this
+ const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
+ std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -3271,12 +4233,6 @@ protected:
{
return new ExternBlock (*this);
}
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual ExternBlock* clone_statement_impl() const override {
- return new ExternBlock(*this);
- }*/
};
// Replaced with forward decls - defined in "rust-macro.h"
diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h
index b51b149..2cae0f9 100644
--- a/gcc/rust/ast/rust-macro.h
+++ b/gcc/rust/ast/rust-macro.h
@@ -124,7 +124,7 @@ private:
public:
// Returns whether macro match repetition has separator token.
- bool has_sep () const { return sep != NULL; }
+ bool has_sep () const { return sep != nullptr; }
MacroMatchRepetition (std::vector<std::unique_ptr<MacroMatch> > matches,
MacroRepOp op, std::unique_ptr<MacroRepSep> sep)
@@ -132,9 +132,12 @@ public:
{}
// Copy constructor with clone
- MacroMatchRepetition (MacroMatchRepetition const &other)
- : op (other.op), sep (other.sep->clone_token ())
+ MacroMatchRepetition (MacroMatchRepetition const &other) : op (other.op)
{
+ // guard to protect from null pointer dereference
+ if (other.sep != nullptr)
+ sep = other.sep->clone_token ();
+
matches.reserve (other.matches.size ());
for (const auto &e : other.matches)
matches.push_back (e->clone_macro_match ());
@@ -144,7 +147,12 @@ public:
MacroMatchRepetition &operator= (MacroMatchRepetition const &other)
{
op = other.op;
- sep = other.sep->clone_token ();
+
+ // guard to protect from null pointer dereference
+ if (other.sep != nullptr)
+ sep = other.sep->clone_token ();
+ else
+ sep = nullptr;
matches.reserve (other.matches.size ());
for (const auto &e : other.matches)
@@ -280,8 +288,9 @@ public:
// A macro rules definition item AST node
class MacroRulesDefinition : public MacroItem
{
+ std::vector<Attribute> outer_attrs;
Identifier rule_name;
- // MacroRulesDef rules_def; // TODO: inline
+ // MacroRulesDef rules_def;
// only curly without required semicolon at end
DelimType delim_type;
// MacroRules rules;
@@ -295,12 +304,23 @@ public:
MacroRulesDefinition (Identifier rule_name, DelimType delim_type,
std::vector<MacroRule> rules,
std::vector<Attribute> outer_attrs, Location locus)
- : MacroItem (std::move (outer_attrs)), rule_name (std::move (rule_name)),
+ : outer_attrs (std::move (outer_attrs)), rule_name (std::move (rule_name)),
delim_type (delim_type), rules (std::move (rules)), locus (locus)
{}
void accept_vis (ASTVisitor &vis) override;
+ // Invalid if rule name is empty, so base stripping on that.
+ void mark_for_strip () override { rule_name = ""; }
+ bool is_marked_for_strip () const override { return rule_name.empty (); }
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
+ const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+
+ std::vector<MacroRule> &get_macro_rules () { return rules; }
+ const std::vector<MacroRule> &get_macro_rules () const { return rules; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -334,6 +354,13 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Invalid if path is empty, so base stripping on that.
+ void mark_for_strip () override { path = SimplePath::create_empty (); }
+ bool is_marked_for_strip () const override { return path.is_empty (); }
+
+ const SimplePath &get_path () const { return path; }
+ SimplePath &get_path () { return path; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -344,13 +371,6 @@ protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
- MacroInvocation *clone_expr_impl () const override
- {
- return new MacroInvocation (*this);
- }
-
- /* Use covariance to implement clone function as returning this object rather
- * than base */
MacroInvocation *clone_expr_without_block_impl () const override
{
return new MacroInvocation (*this);
@@ -358,13 +378,6 @@ protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
- MacroInvocation *clone_type_impl () const override
- {
- return new MacroInvocation (*this);
- }
-
- /* Use covariance to implement clone function as returning this object rather
- * than base */
MacroInvocation *clone_type_no_bounds_impl () const override
{
return new MacroInvocation (*this);
@@ -572,6 +585,8 @@ protected:
};
// Object that parses macros from a token stream.
+/* TODO: would "AttributeParser" be a better name? MetaItems are only for
+ * attributes, I believe */
struct MacroParser
{
private:
diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h
index 3006780..392fc18 100644
--- a/gcc/rust/ast/rust-path.h
+++ b/gcc/rust/ast/rust-path.h
@@ -45,7 +45,6 @@ struct GenericArgsBinding
private:
Identifier identifier;
std::unique_ptr<Type> type;
-
Location locus;
public:
@@ -70,9 +69,12 @@ public:
// Copy constructor has to deep copy the type as it is a unique pointer
GenericArgsBinding (GenericArgsBinding const &other)
- : identifier (other.identifier), type (other.type->clone_type ()),
- locus (other.locus)
- {}
+ : identifier (other.identifier), locus (other.locus)
+ {
+ // guard to protect from null pointer dereference
+ if (other.type != nullptr)
+ type = other.type->clone_type ();
+ }
// default destructor
~GenericArgsBinding () = default;
@@ -81,8 +83,14 @@ public:
GenericArgsBinding &operator= (GenericArgsBinding const &other)
{
identifier = other.identifier;
- type = other.type->clone_type ();
locus = other.locus;
+
+ // guard to protect from null pointer dereference
+ if (other.type != nullptr)
+ type = other.type->clone_type ();
+ else
+ type = nullptr;
+
return *this;
}
@@ -91,13 +99,20 @@ public:
GenericArgsBinding &operator= (GenericArgsBinding &&other) = default;
std::string as_string () const;
+
+ // TODO: is this better? Or is a "vis_pattern" better?
+ std::unique_ptr<Type> &get_type ()
+ {
+ rust_assert (type != nullptr);
+ return type;
+ }
};
// Generic arguments allowed in each path expression segment - inline?
struct GenericArgs
{
std::vector<Lifetime> lifetime_args;
- std::vector<std::unique_ptr<Type>> type_args;
+ std::vector<std::unique_ptr<Type> > type_args;
std::vector<GenericArgsBinding> binding_args;
Location locus;
@@ -110,7 +125,7 @@ public:
}
GenericArgs (std::vector<Lifetime> lifetime_args,
- std::vector<std::unique_ptr<Type>> type_args,
+ std::vector<std::unique_ptr<Type> > type_args,
std::vector<GenericArgsBinding> binding_args,
Location locus = Location ())
: lifetime_args (std::move (lifetime_args)),
@@ -152,11 +167,17 @@ public:
static GenericArgs create_empty ()
{
return GenericArgs (std::vector<Lifetime> (),
- std::vector<std::unique_ptr<Type>> (),
+ std::vector<std::unique_ptr<Type> > (),
std::vector<GenericArgsBinding> ());
}
std::string as_string () const;
+
+ // TODO: is this better? Or is a "vis_pattern" better?
+ std::vector<std::unique_ptr<Type> > &get_type_args () { return type_args; }
+
+ // TODO: is this better? Or is a "vis_pattern" better?
+ std::vector<GenericArgsBinding> &get_binding_args () { return binding_args; }
};
/* A segment of a path in expression, including an identifier aspect and maybe
@@ -189,8 +210,8 @@ public:
PathExprSegment (std::string segment_name, Location locus,
std::vector<Lifetime> lifetime_args
= std::vector<Lifetime> (),
- std::vector<std::unique_ptr<Type>> type_args
- = std::vector<std::unique_ptr<Type>> (),
+ std::vector<std::unique_ptr<Type> > type_args
+ = std::vector<std::unique_ptr<Type> > (),
std::vector<GenericArgsBinding> binding_args
= std::vector<GenericArgsBinding> ())
: segment_name (PathIdentSegment (std::move (segment_name))),
@@ -212,6 +233,13 @@ public:
std::string as_string () const;
Location get_locus () const { return locus; }
+
+ // TODO: is this better? Or is a "vis_pattern" better?
+ GenericArgs &get_generic_args ()
+ {
+ rust_assert (has_generic_args ());
+ return generic_args;
+ }
};
// AST node representing a pattern that involves a "path" - abstract base class
@@ -231,12 +259,23 @@ protected:
* and creates a SimplePath from them. */
SimplePath convert_to_simple_path (bool with_opening_scope_resolution) const;
+ // Removes all segments of the path.
+ void remove_all_segments ()
+ {
+ segments.clear ();
+ segments.shrink_to_fit ();
+ }
+
public:
/* Returns whether the path is a single segment (excluding qualified path
* initial as segment). */
bool is_single_segment () const { return segments.size () == 1; }
std::string as_string () const override;
+
+ // TODO: this seems kinda dodgy
+ std::vector<PathExprSegment> &get_segments () { return segments; }
+ const std::vector<PathExprSegment> &get_segments () const { return segments; }
};
/* AST node representing a path-in-expression pattern (path that allows generic
@@ -286,6 +325,10 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Invalid if path is empty (error state), so base stripping on that.
+ void mark_for_strip () override { remove_all_segments (); }
+ bool is_marked_for_strip () const override { return is_error (); }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -312,7 +355,6 @@ class TypePathSegment
* GenericArgs are, so could disallow that in constructor, which won't give
* that much size overhead. */
PathIdentSegment ident_segment;
-
Location locus;
protected:
@@ -387,7 +429,7 @@ public:
TypePathSegmentGeneric (std::string segment_name,
bool has_separating_scope_resolution,
std::vector<Lifetime> lifetime_args,
- std::vector<std::unique_ptr<Type>> type_args,
+ std::vector<std::unique_ptr<Type> > type_args,
std::vector<GenericArgsBinding> binding_args,
Location locus)
: TypePathSegment (std::move (segment_name),
@@ -401,6 +443,13 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: is this better? Or is a "vis_pattern" better?
+ GenericArgs &get_generic_args ()
+ {
+ rust_assert (has_generic_args ());
+ return generic_args;
+ }
+
protected:
// Use covariance to override base class method
TypePathSegmentGeneric *clone_type_path_segment_impl () const override
@@ -417,7 +466,7 @@ private:
/*bool has_inputs;
TypePathFnInputs inputs;*/
// inlined from TypePathFnInputs
- std::vector<std::unique_ptr<Type>> inputs;
+ std::vector<std::unique_ptr<Type> > inputs;
// bool has_type;
std::unique_ptr<Type> return_type;
@@ -445,14 +494,7 @@ public:
static TypePathFunction create_error () { return TypePathFunction (true); }
// Constructor
- TypePathFunction (std::vector<std::unique_ptr<Type>> inputs,
- Type *type = nullptr)
- : inputs (std::move (inputs)), return_type (type), is_invalid (false)
- {}
- // FIXME: deprecated
-
- // Constructor
- TypePathFunction (std::vector<std::unique_ptr<Type>> inputs,
+ TypePathFunction (std::vector<std::unique_ptr<Type> > inputs,
std::unique_ptr<Type> type = nullptr)
: inputs (std::move (inputs)), return_type (std::move (type)),
is_invalid (false)
@@ -460,9 +502,12 @@ public:
// Copy constructor with clone
TypePathFunction (TypePathFunction const &other)
- : return_type (other.return_type->clone_type ()),
- is_invalid (other.is_invalid)
+ : is_invalid (other.is_invalid)
{
+ // guard to protect from null pointer dereference
+ if (other.return_type != nullptr)
+ return_type = other.return_type->clone_type ();
+
inputs.reserve (other.inputs.size ());
for (const auto &e : other.inputs)
inputs.push_back (e->clone_type ());
@@ -473,9 +518,14 @@ public:
// Overloaded assignment operator to clone type
TypePathFunction &operator= (TypePathFunction const &other)
{
- return_type = other.return_type->clone_type ();
is_invalid = other.is_invalid;
+ // guard to protect from null pointer dereference
+ if (other.return_type != nullptr)
+ return_type = other.return_type->clone_type ();
+ else
+ return_type = nullptr;
+
inputs.reserve (other.inputs.size ());
for (const auto &e : other.inputs)
inputs.push_back (e->clone_type ());
@@ -488,6 +538,20 @@ public:
TypePathFunction &operator= (TypePathFunction &&other) = default;
std::string as_string () const;
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ const std::vector<std::unique_ptr<Type> > &get_params () const
+ {
+ return inputs;
+ }
+ std::vector<std::unique_ptr<Type> > &get_params () { return inputs; }
+
+ // TODO: is this better? Or is a "vis_pattern" better?
+ std::unique_ptr<Type> &get_return_type ()
+ {
+ rust_assert (has_return_type ());
+ return return_type;
+ }
};
// Segment used in type path with a function argument
@@ -520,6 +584,13 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: is this better? Or is a "vis_pattern" better?
+ TypePathFunction &get_type_path_function ()
+ {
+ rust_assert (!function_path.is_error ());
+ return function_path;
+ }
+
protected:
// Use covariance to override base class method
TypePathSegmentFunction *clone_type_path_segment_impl () const override
@@ -531,18 +602,13 @@ protected:
// Path used inside types
class TypePath : public TypeNoBounds
{
-public:
bool has_opening_scope_resolution;
- std::vector<std::unique_ptr<TypePathSegment>> segments;
+ std::vector<std::unique_ptr<TypePathSegment> > segments;
Location locus;
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
- TypePath *clone_type_impl () const override { return new TypePath (*this); }
-
- /* Use covariance to implement clone function as returning this object rather
- * than base */
TypePath *clone_type_no_bounds_impl () const override
{
return new TypePath (*this);
@@ -562,12 +628,12 @@ public:
// Creates an error state TypePath.
static TypePath create_error ()
{
- return TypePath (std::vector<std::unique_ptr<TypePathSegment>> (),
+ return TypePath (std::vector<std::unique_ptr<TypePathSegment> > (),
Location ());
}
// Constructor
- TypePath (std::vector<std::unique_ptr<TypePathSegment>> segments,
+ TypePath (std::vector<std::unique_ptr<TypePathSegment> > segments,
Location locus, bool has_opening_scope_resolution = false)
: has_opening_scope_resolution (has_opening_scope_resolution),
segments (std::move (segments)), locus (locus)
@@ -610,8 +676,19 @@ public:
TraitBound *to_trait_bound (bool in_parens) const override;
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
+
+ // TODO: this seems kinda dodgy
+ std::vector<std::unique_ptr<TypePathSegment> > &get_segments ()
+ {
+ return segments;
+ }
+ const std::vector<std::unique_ptr<TypePathSegment> > &get_segments () const
+ {
+ return segments;
+ }
};
struct QualifiedPathType
@@ -635,9 +712,12 @@ public:
// Copy constructor uses custom deep copy for Type to preserve polymorphism
QualifiedPathType (QualifiedPathType const &other)
- : type_to_invoke_on (other.type_to_invoke_on->clone_type ()),
- trait_path (other.trait_path), locus (other.locus)
- {}
+ : trait_path (other.trait_path), locus (other.locus)
+ {
+ // guard to prevent null dereference
+ if (other.type_to_invoke_on != nullptr)
+ type_to_invoke_on = other.type_to_invoke_on->clone_type ();
+ }
// default destructor
~QualifiedPathType () = default;
@@ -645,9 +725,15 @@ public:
// overload assignment operator to use custom clone method
QualifiedPathType &operator= (QualifiedPathType const &other)
{
- type_to_invoke_on = other.type_to_invoke_on->clone_type ();
trait_path = other.trait_path;
locus = other.locus;
+
+ // guard to prevent null dereference
+ if (other.type_to_invoke_on != nullptr)
+ type_to_invoke_on = other.type_to_invoke_on->clone_type ();
+ else
+ type_to_invoke_on = nullptr;
+
return *this;
}
@@ -670,6 +756,20 @@ public:
std::string as_string () const;
Location get_locus () const { return locus; }
+
+ // TODO: is this better? Or is a "vis_pattern" better?
+ std::unique_ptr<Type> &get_type ()
+ {
+ rust_assert (type_to_invoke_on != nullptr);
+ return type_to_invoke_on;
+ }
+
+ // TODO: is this better? Or is a "vis_pattern" better?
+ TypePath &get_as_type_path ()
+ {
+ rust_assert (has_as_clause ());
+ return trait_path;
+ }
};
/* AST node representing a qualified path-in-expression pattern (path that
@@ -710,6 +810,20 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Invalid if path_type is error, so base stripping on that.
+ void mark_for_strip () override
+ {
+ path_type = QualifiedPathType::create_error ();
+ }
+ bool is_marked_for_strip () const override { return is_error (); }
+
+ // TODO: is this better? Or is a "vis_pattern" better?
+ QualifiedPathType &get_qualified_path_type ()
+ {
+ rust_assert (!path_type.is_error ());
+ return path_type;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -731,19 +845,12 @@ protected:
class QualifiedPathInType : public TypeNoBounds
{
QualifiedPathType path_type;
- std::vector<std::unique_ptr<TypePathSegment>> segments;
+ std::vector<std::unique_ptr<TypePathSegment> > segments;
Location locus;
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
- QualifiedPathInType *clone_type_impl () const override
- {
- return new QualifiedPathInType (*this);
- }
-
- /* Use covariance to implement clone function as returning this object rather
- * than base */
QualifiedPathInType *clone_type_no_bounds_impl () const override
{
return new QualifiedPathInType (*this);
@@ -752,7 +859,7 @@ protected:
public:
QualifiedPathInType (
QualifiedPathType qual_path_type,
- std::vector<std::unique_ptr<TypePathSegment>> path_segments,
+ std::vector<std::unique_ptr<TypePathSegment> > path_segments,
Location locus = Location ())
: path_type (std::move (qual_path_type)),
segments (std::move (path_segments)), locus (locus)
@@ -795,12 +902,32 @@ public:
{
return QualifiedPathInType (
QualifiedPathType::create_error (),
- std::vector<std::unique_ptr<TypePathSegment>> ());
+ std::vector<std::unique_ptr<TypePathSegment> > ());
}
std::string as_string () const override;
void accept_vis (ASTVisitor &vis) override;
+
+ // TODO: is this better? Or is a "vis_pattern" better?
+ QualifiedPathType &get_qualified_path_type ()
+ {
+ rust_assert (!path_type.is_error ());
+ return path_type;
+ }
+
+ // TODO: this seems kinda dodgy
+ std::vector<std::unique_ptr<TypePathSegment> > &get_segments ()
+ {
+ return segments;
+ }
+ const std::vector<std::unique_ptr<TypePathSegment> > &get_segments () const
+ {
+ return segments;
+ }
+
+ Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
};
} // namespace AST
} // namespace Rust
diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h
index 4e639a5..3a87a83 100644
--- a/gcc/rust/ast/rust-pattern.h
+++ b/gcc/rust/ast/rust-pattern.h
@@ -34,6 +34,7 @@ public:
{}
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
@@ -49,7 +50,6 @@ protected:
// Identifier pattern AST node (bind value matched to a variable)
class IdentifierPattern : public Pattern
{
-public:
Identifier variable_ident;
bool is_ref;
bool is_mut;
@@ -59,6 +59,7 @@ public:
Location locus;
+public:
std::string as_string () const;
// Returns whether the IdentifierPattern has a pattern to bind.
@@ -77,7 +78,7 @@ public:
: variable_ident (other.variable_ident), is_ref (other.is_ref),
is_mut (other.is_mut), locus (other.locus)
{
- // fix to get prevent null pointer dereference
+ // fix to prevent null pointer dereference
if (other.to_bind != nullptr)
to_bind = other.to_bind->clone_pattern ();
}
@@ -90,9 +91,11 @@ public:
is_mut = other.is_mut;
locus = other.locus;
- // fix to get prevent null pointer dereference
+ // fix to prevent null pointer dereference
if (other.to_bind != nullptr)
to_bind = other.to_bind->clone_pattern ();
+ else
+ to_bind = nullptr;
return *this;
}
@@ -102,9 +105,19 @@ public:
IdentifierPattern &operator= (IdentifierPattern &&other) = default;
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
+ // TODO: is this better? Or is a "vis_pattern" better?
+ std::unique_ptr<Pattern> &get_pattern_to_bind ()
+ {
+ rust_assert (has_pattern_to_bind ());
+ return to_bind;
+ }
+
+ Identifier get_ident () const { return variable_ident; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -125,6 +138,7 @@ public:
WildcardPattern (Location locus) : locus (locus) {}
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
@@ -210,6 +224,10 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: this mutable getter seems kinda dodgy
+ PathInExpression &get_path () { return path; }
+ const PathInExpression &get_path () const { return path; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -238,6 +256,10 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: this mutable getter seems kinda dodgy
+ QualifiedPathInExpression &get_qualified_path () { return path; }
+ const QualifiedPathInExpression &get_qualified_path () const { return path; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -293,9 +315,23 @@ public:
RangePattern &operator= (RangePattern &&other) = default;
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
+ // TODO: is this better? or is a "vis_bound" better?
+ std::unique_ptr<RangePatternBound> &get_lower_bound ()
+ {
+ rust_assert (lower != nullptr);
+ return lower;
+ }
+
+ std::unique_ptr<RangePatternBound> &get_upper_bound ()
+ {
+ rust_assert (upper != nullptr);
+ return upper;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -343,8 +379,18 @@ public:
ReferencePattern (ReferencePattern &&other) = default;
ReferencePattern &operator= (ReferencePattern &&other) = default;
+ Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
+
void accept_vis (ASTVisitor &vis) override;
+ // TODO: is this better? Or is a "vis_pattern" better?
+ std::unique_ptr<Pattern> &get_referenced_pattern ()
+ {
+ rust_assert (pattern != nullptr);
+ return pattern;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -354,6 +400,7 @@ protected:
}
};
+#if 0
// aka StructPatternEtCetera; potential element in struct pattern
struct StructPatternEtc
{
@@ -373,6 +420,7 @@ public:
return StructPatternEtc (std::vector<Attribute> ());
}
};
+#endif
// Base class for a single field in a struct pattern - abstract
class StructPatternField
@@ -396,6 +444,13 @@ public:
virtual void accept_vis (ASTVisitor &vis) = 0;
+ virtual void mark_for_strip () = 0;
+ virtual bool is_marked_for_strip () const = 0;
+
+ // TODO: seems kinda dodgy. Think of better way.
+ std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
+ const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+
protected:
StructPatternField (std::vector<Attribute> outer_attribs, Location locus)
: outer_attrs (std::move (outer_attribs)), locus (locus)
@@ -422,19 +477,27 @@ public:
// Copy constructor requires clone
StructPatternFieldTuplePat (StructPatternFieldTuplePat const &other)
- : StructPatternField (other), index (other.index),
- tuple_pattern (other.tuple_pattern->clone_pattern ())
- {}
+ : StructPatternField (other), index (other.index)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.tuple_pattern != nullptr)
+ tuple_pattern = other.tuple_pattern->clone_pattern ();
+ }
// Overload assignment operator to perform clone
StructPatternFieldTuplePat &
operator= (StructPatternFieldTuplePat const &other)
{
StructPatternField::operator= (other);
- tuple_pattern = other.tuple_pattern->clone_pattern ();
index = other.index;
// outer_attrs = other.outer_attrs;
+ // guard to prevent null dereference (only required if error state)
+ if (other.tuple_pattern != nullptr)
+ tuple_pattern = other.tuple_pattern->clone_pattern ();
+ else
+ tuple_pattern = nullptr;
+
return *this;
}
@@ -447,6 +510,20 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // based on idea of tuple pattern no longer existing
+ void mark_for_strip () override { tuple_pattern = nullptr; }
+ bool is_marked_for_strip () const override
+ {
+ return tuple_pattern == nullptr;
+ }
+
+ // TODO: is this better? Or is a "vis_pattern" better?
+ std::unique_ptr<Pattern> &get_index_pattern ()
+ {
+ rust_assert (tuple_pattern != nullptr);
+ return tuple_pattern;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -473,9 +550,12 @@ public:
// Copy constructor requires clone
StructPatternFieldIdentPat (StructPatternFieldIdentPat const &other)
- : StructPatternField (other), ident (other.ident),
- ident_pattern (other.ident_pattern->clone_pattern ())
- {}
+ : StructPatternField (other), ident (other.ident)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.ident_pattern != nullptr)
+ ident_pattern = other.ident_pattern->clone_pattern ();
+ }
// Overload assignment operator to clone
StructPatternFieldIdentPat &
@@ -483,9 +563,14 @@ public:
{
StructPatternField::operator= (other);
ident = other.ident;
- ident_pattern = other.ident_pattern->clone_pattern ();
// outer_attrs = other.outer_attrs;
+ // guard to prevent null dereference (only required if error state)
+ if (other.ident_pattern != nullptr)
+ ident_pattern = other.ident_pattern->clone_pattern ();
+ else
+ ident_pattern = nullptr;
+
return *this;
}
@@ -498,6 +583,20 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // based on idea of identifier pattern no longer existing
+ void mark_for_strip () override { ident_pattern = nullptr; }
+ bool is_marked_for_strip () const override
+ {
+ return ident_pattern == nullptr;
+ }
+
+ // TODO: is this better? Or is a "vis_pattern" better?
+ std::unique_ptr<Pattern> &get_ident_pattern ()
+ {
+ rust_assert (ident_pattern != nullptr);
+ return ident_pattern;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -525,6 +624,10 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // based on idea of identifier no longer existing
+ void mark_for_strip () override { ident = {}; }
+ bool is_marked_for_strip () const override { return ident.empty (); }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -539,10 +642,11 @@ struct StructPatternElements
{
private:
// bool has_struct_pattern_fields;
- std::vector<std::unique_ptr<StructPatternField>> fields;
+ std::vector<std::unique_ptr<StructPatternField> > fields;
bool has_struct_pattern_etc;
- StructPatternEtc etc;
+ std::vector<Attribute> struct_pattern_etc_attrs;
+ // StructPatternEtc etc;
// must have at least one of the two and maybe both
@@ -559,24 +663,27 @@ public:
return !has_struct_pattern_fields () && !has_struct_pattern_etc;
}
+ bool has_etc () const { return has_struct_pattern_etc; }
+
// Constructor for StructPatternElements with both (potentially)
StructPatternElements (
- std::vector<std::unique_ptr<StructPatternField>> fields,
- StructPatternEtc etc)
+ std::vector<std::unique_ptr<StructPatternField> > fields,
+ std::vector<Attribute> etc_attrs)
: fields (std::move (fields)), has_struct_pattern_etc (true),
- etc (std::move (etc))
+ struct_pattern_etc_attrs (std::move (etc_attrs))
{}
// Constructor for StructPatternElements with no StructPatternEtc
StructPatternElements (
- std::vector<std::unique_ptr<StructPatternField>> fields)
+ std::vector<std::unique_ptr<StructPatternField> > fields)
: fields (std::move (fields)), has_struct_pattern_etc (false),
- etc (StructPatternEtc::create_empty ())
+ struct_pattern_etc_attrs ()
{}
// Copy constructor with vector clone
StructPatternElements (StructPatternElements const &other)
- : has_struct_pattern_etc (other.has_struct_pattern_etc), etc (other.etc)
+ : has_struct_pattern_etc (other.has_struct_pattern_etc),
+ struct_pattern_etc_attrs (other.struct_pattern_etc_attrs)
{
fields.reserve (other.fields.size ());
for (const auto &e : other.fields)
@@ -586,7 +693,7 @@ public:
// Overloaded assignment operator with vector clone
StructPatternElements &operator= (StructPatternElements const &other)
{
- etc = other.etc;
+ struct_pattern_etc_attrs = other.struct_pattern_etc_attrs;
has_struct_pattern_etc = other.has_struct_pattern_etc;
fields.reserve (other.fields.size ());
@@ -604,10 +711,38 @@ public:
static StructPatternElements create_empty ()
{
return StructPatternElements (
- std::vector<std::unique_ptr<StructPatternField>> ());
+ std::vector<std::unique_ptr<StructPatternField> > ());
}
std::string as_string () const;
+
+ // TODO: seems kinda dodgy. Think of better way.
+ std::vector<std::unique_ptr<StructPatternField> > &
+ get_struct_pattern_fields ()
+ {
+ return fields;
+ }
+ const std::vector<std::unique_ptr<StructPatternField> > &
+ get_struct_pattern_fields () const
+ {
+ return fields;
+ }
+
+ std::vector<Attribute> &get_etc_outer_attrs ()
+ {
+ return struct_pattern_etc_attrs;
+ }
+ const std::vector<Attribute> &get_etc_outer_attrs () const
+ {
+ return struct_pattern_etc_attrs;
+ }
+
+ void strip_etc ()
+ {
+ has_struct_pattern_etc = false;
+ struct_pattern_etc_attrs.clear ();
+ struct_pattern_etc_attrs.shrink_to_fit ();
+ }
};
// Struct pattern AST node representation
@@ -638,9 +773,20 @@ public:
bool has_struct_pattern_elems () const { return !elems.is_empty (); }
Location get_locus () const { return path.get_locus (); }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
+ // TODO: seems kinda dodgy. Think of better way.
+ StructPatternElements &get_struct_pattern_elems () { return elems; }
+ const StructPatternElements &get_struct_pattern_elems () const
+ {
+ return elems;
+ }
+
+ PathInExpression &get_path () { return path; }
+ const PathInExpression &get_path () const { return path; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -676,10 +822,10 @@ protected:
// Class for non-ranged tuple struct pattern patterns
class TupleStructItemsNoRange : public TupleStructItems
{
- std::vector<std::unique_ptr<Pattern>> patterns;
+ std::vector<std::unique_ptr<Pattern> > patterns;
public:
- TupleStructItemsNoRange (std::vector<std::unique_ptr<Pattern>> patterns)
+ TupleStructItemsNoRange (std::vector<std::unique_ptr<Pattern> > patterns)
: patterns (std::move (patterns))
{}
@@ -710,6 +856,13 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: seems kinda dodgy. Think of better way.
+ std::vector<std::unique_ptr<Pattern> > &get_patterns () { return patterns; }
+ const std::vector<std::unique_ptr<Pattern> > &get_patterns () const
+ {
+ return patterns;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -722,12 +875,12 @@ protected:
// Class for ranged tuple struct pattern patterns
class TupleStructItemsRange : public TupleStructItems
{
- std::vector<std::unique_ptr<Pattern>> lower_patterns;
- std::vector<std::unique_ptr<Pattern>> upper_patterns;
+ std::vector<std::unique_ptr<Pattern> > lower_patterns;
+ std::vector<std::unique_ptr<Pattern> > upper_patterns;
public:
- TupleStructItemsRange (std::vector<std::unique_ptr<Pattern>> lower_patterns,
- std::vector<std::unique_ptr<Pattern>> upper_patterns)
+ TupleStructItemsRange (std::vector<std::unique_ptr<Pattern> > lower_patterns,
+ std::vector<std::unique_ptr<Pattern> > upper_patterns)
: lower_patterns (std::move (lower_patterns)),
upper_patterns (std::move (upper_patterns))
{}
@@ -766,6 +919,26 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: seems kinda dodgy. Think of better way.
+ std::vector<std::unique_ptr<Pattern> > &get_lower_patterns ()
+ {
+ return lower_patterns;
+ }
+ const std::vector<std::unique_ptr<Pattern> > &get_lower_patterns () const
+ {
+ return lower_patterns;
+ }
+
+ // TODO: seems kinda dodgy. Think of better way.
+ std::vector<std::unique_ptr<Pattern> > &get_upper_patterns ()
+ {
+ return upper_patterns;
+ }
+ const std::vector<std::unique_ptr<Pattern> > &get_upper_patterns () const
+ {
+ return upper_patterns;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -787,21 +960,32 @@ class TupleStructPattern : public Pattern
public:
std::string as_string () const override;
+ // Returns whether the pattern has tuple struct items.
+ bool has_items () const { return items != nullptr; }
+
TupleStructPattern (PathInExpression tuple_struct_path,
std::unique_ptr<TupleStructItems> items)
: path (std::move (tuple_struct_path)), items (std::move (items))
{}
// Copy constructor required to clone
- TupleStructPattern (TupleStructPattern const &other)
- : path (other.path), items (other.items->clone_tuple_struct_items ())
- {}
+ TupleStructPattern (TupleStructPattern const &other) : path (other.path)
+ {
+ // guard to protect from null dereference
+ if (other.items != nullptr)
+ items = other.items->clone_tuple_struct_items ();
+ }
// Operator overload assignment operator to clone
TupleStructPattern &operator= (TupleStructPattern const &other)
{
path = other.path;
- items = other.items->clone_tuple_struct_items ();
+
+ // guard to protect from null dereference
+ if (other.items != nullptr)
+ items = other.items->clone_tuple_struct_items ();
+ else
+ items = nullptr;
return *this;
}
@@ -811,9 +995,20 @@ public:
TupleStructPattern &operator= (TupleStructPattern &&other) = default;
Location get_locus () const { return path.get_locus (); }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
+ // TODO: seems kinda dodgy. Think of better way.
+ std::unique_ptr<TupleStructItems> &get_items ()
+ {
+ rust_assert (has_items ());
+ return items;
+ }
+
+ PathInExpression &get_path () { return path; }
+ const PathInExpression &get_path () const { return path; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -885,10 +1080,10 @@ TuplePatternItemsSingle(*this);
// Class representing TuplePattern patterns where there are multiple patterns
class TuplePatternItemsMultiple : public TuplePatternItems
{
- std::vector<std::unique_ptr<Pattern>> patterns;
+ std::vector<std::unique_ptr<Pattern> > patterns;
public:
- TuplePatternItemsMultiple (std::vector<std::unique_ptr<Pattern>> patterns)
+ TuplePatternItemsMultiple (std::vector<std::unique_ptr<Pattern> > patterns)
: patterns (std::move (patterns))
{}
@@ -919,6 +1114,13 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: seems kinda dodgy. Think of better way.
+ std::vector<std::unique_ptr<Pattern> > &get_patterns () { return patterns; }
+ const std::vector<std::unique_ptr<Pattern> > &get_patterns () const
+ {
+ return patterns;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -931,13 +1133,13 @@ protected:
// Class representing TuplePattern patterns where there are a range of patterns
class TuplePatternItemsRanged : public TuplePatternItems
{
- std::vector<std::unique_ptr<Pattern>> lower_patterns;
- std::vector<std::unique_ptr<Pattern>> upper_patterns;
+ std::vector<std::unique_ptr<Pattern> > lower_patterns;
+ std::vector<std::unique_ptr<Pattern> > upper_patterns;
public:
TuplePatternItemsRanged (
- std::vector<std::unique_ptr<Pattern>> lower_patterns,
- std::vector<std::unique_ptr<Pattern>> upper_patterns)
+ std::vector<std::unique_ptr<Pattern> > lower_patterns,
+ std::vector<std::unique_ptr<Pattern> > upper_patterns)
: lower_patterns (std::move (lower_patterns)),
upper_patterns (std::move (upper_patterns))
{}
@@ -977,6 +1179,26 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: seems kinda dodgy. Think of better way.
+ std::vector<std::unique_ptr<Pattern> > &get_lower_patterns ()
+ {
+ return lower_patterns;
+ }
+ const std::vector<std::unique_ptr<Pattern> > &get_lower_patterns () const
+ {
+ return lower_patterns;
+ }
+
+ // TODO: seems kinda dodgy. Think of better way.
+ std::vector<std::unique_ptr<Pattern> > &get_upper_patterns ()
+ {
+ return upper_patterns;
+ }
+ const std::vector<std::unique_ptr<Pattern> > &get_upper_patterns () const
+ {
+ return upper_patterns;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -991,7 +1213,6 @@ class TuplePattern : public Pattern
{
// bool has_tuple_pattern_items;
std::unique_ptr<TuplePatternItems> items;
-
Location locus;
public:
@@ -1005,23 +1226,39 @@ public:
{}
// Copy constructor requires clone
- TuplePattern (TuplePattern const &other)
- : items (other.items->clone_tuple_pattern_items ()), locus (other.locus)
- {}
+ TuplePattern (TuplePattern const &other) : locus (other.locus)
+ {
+ // guard to prevent null dereference
+ if (other.items != nullptr)
+ items = other.items->clone_tuple_pattern_items ();
+ }
// Overload assignment operator to clone
TuplePattern &operator= (TuplePattern const &other)
{
- items = other.items->clone_tuple_pattern_items ();
locus = other.locus;
+ // guard to prevent null dereference
+ if (other.items != nullptr)
+ items = other.items->clone_tuple_pattern_items ();
+ else
+ items = nullptr;
+
return *this;
}
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
+ // TODO: seems kinda dodgy. Think of better way.
+ std::unique_ptr<TuplePatternItems> &get_items ()
+ {
+ rust_assert (has_tuple_pattern_items ());
+ return items;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1067,9 +1304,17 @@ public:
GroupedPattern &operator= (GroupedPattern &&other) = default;
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
+ // TODO: seems kinda dodgy. Think of better way.
+ std::unique_ptr<Pattern> &get_pattern_in_parens ()
+ {
+ rust_assert (pattern_in_parens != nullptr);
+ return pattern_in_parens;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1082,13 +1327,13 @@ protected:
// AST node representing patterns that can match slices and arrays
class SlicePattern : public Pattern
{
- std::vector<std::unique_ptr<Pattern>> items;
+ std::vector<std::unique_ptr<Pattern> > items;
Location locus;
public:
std::string as_string () const override;
- SlicePattern (std::vector<std::unique_ptr<Pattern>> items, Location locus)
+ SlicePattern (std::vector<std::unique_ptr<Pattern> > items, Location locus)
: items (std::move (items)), locus (locus)
{}
@@ -1117,9 +1362,17 @@ public:
SlicePattern &operator= (SlicePattern &&other) = default;
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
+ // TODO: seems kinda dodgy. Think of better way.
+ std::vector<std::unique_ptr<Pattern> > &get_items () { return items; }
+ const std::vector<std::unique_ptr<Pattern> > &get_items () const
+ {
+ return items;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
diff --git a/gcc/rust/ast/rust-stmt.h b/gcc/rust/ast/rust-stmt.h
index ce7a37a..faea905 100644
--- a/gcc/rust/ast/rust-stmt.h
+++ b/gcc/rust/ast/rust-stmt.h
@@ -12,6 +12,9 @@ class EmptyStmt : public Stmt
{
Location locus;
+ // TODO: find another way to store this to save memory?
+ bool marked_for_strip = false;
+
public:
std::string as_string () const override { return std::string (1, ';'); }
@@ -21,6 +24,10 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Can't think of any invalid invariants, so store boolean.
+ void mark_for_strip () override { marked_for_strip = true; }
+ bool is_marked_for_strip () const override { return marked_for_strip; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -31,7 +38,6 @@ protected:
* introduces new name into scope */
class LetStmt : public Stmt
{
-public:
// bool has_outer_attrs;
std::vector<Attribute> outer_attrs;
@@ -45,6 +51,7 @@ public:
Location locus;
+public:
Type *inferedType;
// Returns whether let statement has outer attributes.
@@ -68,21 +75,41 @@ public:
// Copy constructor with clone
LetStmt (LetStmt const &other)
- : outer_attrs (other.outer_attrs),
- variables_pattern (other.variables_pattern->clone_pattern ()),
- type (other.type->clone_type ()),
- init_expr (other.init_expr->clone_expr ()), locus (other.locus)
- {}
+ : outer_attrs (other.outer_attrs), locus (other.locus)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.variables_pattern != nullptr)
+ variables_pattern = other.variables_pattern->clone_pattern ();
+
+ // guard to prevent null dereference (always required)
+ if (other.init_expr != nullptr)
+ init_expr = other.init_expr->clone_expr ();
+ if (other.type != nullptr)
+ type = other.type->clone_type ();
+ }
// Overloaded assignment operator to clone
LetStmt &operator= (LetStmt const &other)
{
- variables_pattern = other.variables_pattern->clone_pattern ();
- init_expr = other.init_expr->clone_expr ();
- type = other.type->clone_type ();
outer_attrs = other.outer_attrs;
locus = other.locus;
+ // guard to prevent null dereference (only required if error state)
+ if (other.variables_pattern != nullptr)
+ variables_pattern = other.variables_pattern->clone_pattern ();
+ else
+ variables_pattern = nullptr;
+
+ // guard to prevent null dereference (always required)
+ if (other.init_expr != nullptr)
+ init_expr = other.init_expr->clone_expr ();
+ else
+ init_expr = nullptr;
+ if (other.type != nullptr)
+ type = other.type->clone_type ();
+ else
+ type = nullptr;
+
return *this;
}
@@ -94,6 +121,36 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Invalid if pattern is null, so base stripping on that.
+ void mark_for_strip () override { variables_pattern = nullptr; }
+ bool is_marked_for_strip () const override
+ {
+ return variables_pattern == nullptr;
+ }
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
+ const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_init_expr ()
+ {
+ rust_assert (has_init_expr ());
+ return init_expr;
+ }
+
+ std::unique_ptr<Pattern> &get_pattern ()
+ {
+ rust_assert (variables_pattern != nullptr);
+ return variables_pattern;
+ }
+
+ std::unique_ptr<Type> &get_type ()
+ {
+ rust_assert (has_type ());
+ return type;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -119,7 +176,6 @@ protected:
* difficulties, can only be guaranteed to hold an expression). */
class ExprStmtWithoutBlock : public ExprStmt
{
-public:
// TODO: ensure that this works
std::unique_ptr<ExprWithoutBlock> expr;
/* HACK: cannot ensure type safety of ExprWithoutBlock due to Pratt parsing,
@@ -127,6 +183,7 @@ public:
* or redesign AST. */
// std::unique_ptr<Expr> expr;
+public:
std::string as_string () const override;
ExprStmtWithoutBlock (std::unique_ptr<ExprWithoutBlock> expr, Location locus)
@@ -137,9 +194,12 @@ public:
{}*/
// Copy constructor with clone
- ExprStmtWithoutBlock (ExprStmtWithoutBlock const &other)
- : ExprStmt (other), expr (other.expr->clone_expr_without_block ())
- {}
+ ExprStmtWithoutBlock (ExprStmtWithoutBlock const &other) : ExprStmt (other)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.expr != nullptr)
+ expr = other.expr->clone_expr_without_block ();
+ }
/*ExprStmtWithoutBlock (ExprStmtWithoutBlock const &other)
: ExprStmt (other), expr (other.expr->clone_expr ())
{}*/
@@ -148,8 +208,13 @@ public:
ExprStmtWithoutBlock &operator= (ExprStmtWithoutBlock const &other)
{
ExprStmt::operator= (other);
- expr = other.expr->clone_expr_without_block ();
- //expr = other.expr->clone_expr ();
+ // expr = other.expr->clone_expr ();
+
+ // guard to prevent null dereference (only required if error state)
+ if (other.expr != nullptr)
+ expr = other.expr->clone_expr_without_block ();
+ else
+ expr = nullptr;
return *this;
}
@@ -160,6 +225,17 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Invalid if expr is null, so base stripping on that.
+ void mark_for_strip () override { expr = nullptr; }
+ bool is_marked_for_strip () const override { return expr == nullptr; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<ExprWithoutBlock> &get_expr ()
+ {
+ rust_assert (expr != nullptr);
+ return expr;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -172,9 +248,9 @@ protected:
// Statement containing an expression with a block
class ExprStmtWithBlock : public ExprStmt
{
-public:
std::unique_ptr<ExprWithBlock> expr;
+public:
std::string as_string () const override;
std::vector<LetStmt *> locals;
@@ -184,15 +260,23 @@ public:
{}
// Copy constructor with clone
- ExprStmtWithBlock (ExprStmtWithBlock const &other)
- : ExprStmt (other), expr (other.expr->clone_expr_with_block ())
- {}
+ ExprStmtWithBlock (ExprStmtWithBlock const &other) : ExprStmt (other)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.expr != nullptr)
+ expr = other.expr->clone_expr_with_block ();
+ }
// Overloaded assignment operator to clone
ExprStmtWithBlock &operator= (ExprStmtWithBlock const &other)
{
ExprStmt::operator= (other);
- expr = other.expr->clone_expr_with_block ();
+
+ // guard to prevent null dereference (only required if error state)
+ if (other.expr != nullptr)
+ expr = other.expr->clone_expr_with_block ();
+ else
+ expr = nullptr;
return *this;
}
@@ -203,6 +287,17 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Invalid if expr is null, so base stripping on that.
+ void mark_for_strip () override { expr = nullptr; }
+ bool is_marked_for_strip () const override { return expr == nullptr; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<ExprWithBlock> &get_expr ()
+ {
+ rust_assert (expr != nullptr);
+ return expr;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h
index 089aaeb..8c175d3 100644
--- a/gcc/rust/ast/rust-type.h
+++ b/gcc/rust/ast/rust-type.h
@@ -43,6 +43,10 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: this mutable getter seems kinda dodgy
+ TypePath &get_type_path () { return type_path; }
+ const TypePath &get_type_path () const { return type_path; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -106,8 +110,20 @@ public:
std::string as_string () const override;
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
+
+ // TODO: mutable getter seems kinda dodgy
+ std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds ()
+ {
+ return type_param_bounds;
+ }
+ const std::vector<std::unique_ptr<TypeParamBound> > &
+ get_type_param_bounds () const
+ {
+ return type_param_bounds;
+ }
};
// An opaque value of another type that implements a set of traits
@@ -164,8 +180,20 @@ public:
std::string as_string () const override;
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
+
+ // TODO: mutable getter seems kinda dodgy
+ std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds ()
+ {
+ return type_param_bounds;
+ }
+ const std::vector<std::unique_ptr<TypeParamBound> > &
+ get_type_param_bounds () const
+ {
+ return type_param_bounds;
+ }
};
// A type with parentheses around it, used to avoid ambiguity.
@@ -177,13 +205,6 @@ class ParenthesisedType : public TypeNoBounds
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
- ParenthesisedType *clone_type_impl () const override
- {
- return new ParenthesisedType (*this);
- }
-
- /* Use covariance to implement clone function as returning this object rather
- * than base */
ParenthesisedType *clone_type_no_bounds_impl () const override
{
return new ParenthesisedType (*this);
@@ -219,7 +240,7 @@ public:
}
// Creates a trait bound (clone of this one's trait bound) - HACK
- TraitBound *to_trait_bound (bool in_parens ATTRIBUTE_UNUSED) const override
+ TraitBound *to_trait_bound (bool) const override
{
/* NOTE: obviously it is unknown whether the internal type is a trait bound
* due to polymorphism, so just let the internal type handle it. As
@@ -228,27 +249,27 @@ public:
}
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
+
+ // TODO: would a "vis_type" be better?
+ std::unique_ptr<Type> &get_type_in_parens ()
+ {
+ rust_assert (type_in_parens != nullptr);
+ return type_in_parens;
+ }
};
// Impl trait with a single bound? Poor reference material here.
class ImplTraitTypeOneBound : public TypeNoBounds
{
TraitBound trait_bound;
-
Location locus;
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
- ImplTraitTypeOneBound *clone_type_impl () const override
- {
- return new ImplTraitTypeOneBound (*this);
- }
-
- /* Use covariance to implement clone function as returning this object rather
- * than base */
ImplTraitTypeOneBound *clone_type_no_bounds_impl () const override
{
return new ImplTraitTypeOneBound (*this);
@@ -262,8 +283,16 @@ public:
std::string as_string () const override;
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
+
+ // TODO: would a "vis_type" be better?
+ TraitBound &get_trait_bound ()
+ {
+ // TODO: check to ensure invariants are met?
+ return trait_bound;
+ }
};
/* A trait object with a single trait bound. The "trait bound" is really just
@@ -272,19 +301,11 @@ class TraitObjectTypeOneBound : public TypeNoBounds
{
bool has_dyn;
TraitBound trait_bound;
-
Location locus;
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
- TraitObjectTypeOneBound *clone_type_impl () const override
- {
- return new TraitObjectTypeOneBound (*this);
- }
-
- /* Use covariance to implement clone function as returning this object rather
- * than base */
TraitObjectTypeOneBound *clone_type_no_bounds_impl () const override
{
return new TraitObjectTypeOneBound (*this);
@@ -300,16 +321,24 @@ public:
std::string as_string () const override;
// Creates a trait bound (clone of this one's trait bound) - HACK
- TraitBound *to_trait_bound (bool in_parens ATTRIBUTE_UNUSED) const override
+ TraitBound *to_trait_bound (bool) const override
{
/* NOTE: this assumes there is no dynamic dispatch specified- if there was,
* this cloning would not be required as parsing is unambiguous. */
- return new AST::TraitBound (trait_bound);
+ return new TraitBound (trait_bound);
}
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
+
+ // TODO: would a "vis_type" be better?
+ TraitBound &get_trait_bound ()
+ {
+ // TODO: check to ensure invariants are met?
+ return trait_bound;
+ }
};
class TypePath; // definition moved to "rust-path.h"
@@ -356,14 +385,18 @@ public:
std::string as_string () const override;
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- TupleType *clone_type_impl () const override { return new TupleType (*this); }
+ // TODO: mutable getter seems kinda dodgy
+ std::vector<std::unique_ptr<Type> > &get_elems () { return elems; }
+ const std::vector<std::unique_ptr<Type> > &get_elems () const
+ {
+ return elems;
+ }
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
TupleType *clone_type_no_bounds_impl () const override
@@ -382,10 +415,6 @@ class NeverType : public TypeNoBounds
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
- NeverType *clone_type_impl () const override { return new NeverType (*this); }
-
- /* Use covariance to implement clone function as returning this object rather
- * than base */
NeverType *clone_type_no_bounds_impl () const override
{
return new NeverType (*this);
@@ -397,6 +426,7 @@ public:
std::string as_string () const override { return "! (never type)"; }
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
};
@@ -449,17 +479,18 @@ public:
std::string as_string () const override;
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- RawPointerType *clone_type_impl () const override
+ // TODO: would a "vis_type" be better?
+ std::unique_ptr<TypeNoBounds> &get_type_pointed_to ()
{
- return new RawPointerType (*this);
+ rust_assert (type != nullptr);
+ return type;
}
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
RawPointerType *clone_type_no_bounds_impl () const override
@@ -516,17 +547,18 @@ public:
std::string as_string () const override;
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- ReferenceType *clone_type_impl () const override
+ // TODO: would a "vis_type" be better?
+ std::unique_ptr<TypeNoBounds> &get_type_referenced ()
{
- return new ReferenceType (*this);
+ rust_assert (type != nullptr);
+ return type;
}
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
ReferenceType *clone_type_no_bounds_impl () const override
@@ -571,22 +603,27 @@ public:
std::string as_string () const override;
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
- Type *get_element_type () { return elem_type.get (); }
-
- Expr *get_size_expr () { return size.get (); }
+ // TODO: would a "vis_type" be better?
+ std::unique_ptr<Type> &get_elem_type ()
+ {
+ rust_assert (elem_type != nullptr);
+ return elem_type;
+ }
- Location &get_locus () { return locus; }
+ // TODO: would a "vis_expr" be better?
+ std::unique_ptr<Expr> &get_size_expr ()
+ {
+ rust_assert (size != nullptr);
+ return size;
+ }
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
- ArrayType *clone_type_impl () const override { return new ArrayType (*this); }
-
- /* Use covariance to implement clone function as returning this object rather
- * than base */
ArrayType *clone_type_no_bounds_impl () const override
{
return new ArrayType (*this);
@@ -627,14 +664,18 @@ public:
std::string as_string () const override;
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- SliceType *clone_type_impl () const override { return new SliceType (*this); }
+ // TODO: would a "vis_type" be better?
+ std::unique_ptr<Type> &get_elem_type ()
+ {
+ rust_assert (elem_type != nullptr);
+ return elem_type;
+ }
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
SliceType *clone_type_no_bounds_impl () const override
@@ -653,13 +694,6 @@ class InferredType : public TypeNoBounds
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
- InferredType *clone_type_impl () const override
- {
- return new InferredType (*this);
- }
-
- /* Use covariance to implement clone function as returning this object rather
- * than base */
InferredType *clone_type_no_bounds_impl () const override
{
return new InferredType (*this);
@@ -671,6 +705,7 @@ public:
std::string as_string () const override;
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
};
@@ -689,6 +724,8 @@ public:
};
private:
+ std::vector<Attribute> outer_attrs;
+
std::unique_ptr<Type> param_type;
ParamKind param_kind;
@@ -698,27 +735,39 @@ private:
public:
MaybeNamedParam (Identifier name, ParamKind param_kind,
- std::unique_ptr<Type> param_type, Location locus)
- : param_type (std::move (param_type)), param_kind (param_kind),
+ std::unique_ptr<Type> param_type,
+ std::vector<Attribute> outer_attrs, Location locus)
+ : outer_attrs (std::move (outer_attrs)),
+ param_type (std::move (param_type)), param_kind (param_kind),
name (std::move (name)), locus (locus)
{}
// Copy constructor with clone
MaybeNamedParam (MaybeNamedParam const &other)
- : param_type (other.param_type->clone_type ()),
- param_kind (other.param_kind), name (other.name), locus (other.locus)
- {}
+ : outer_attrs (other.outer_attrs), param_kind (other.param_kind),
+ name (other.name), locus (other.locus)
+ {
+ // guard to prevent null dereference
+ if (other.param_type != nullptr)
+ param_type = other.param_type->clone_type ();
+ }
~MaybeNamedParam () = default;
// Overloaded assignment operator with clone
MaybeNamedParam &operator= (MaybeNamedParam const &other)
{
+ outer_attrs = other.outer_attrs;
name = other.name;
param_kind = other.param_kind;
- param_type = other.param_type->clone_type ();
locus = other.locus;
+ // guard to prevent null dereference
+ if (other.param_type != nullptr)
+ param_type = other.param_type->clone_type ();
+ else
+ param_type = nullptr;
+
return *this;
}
@@ -734,10 +783,21 @@ public:
// Creates an error state param.
static MaybeNamedParam create_error ()
{
- return MaybeNamedParam ("", UNNAMED, nullptr, Location ());
+ return MaybeNamedParam ("", UNNAMED, nullptr, {}, Location ());
}
Location get_locus () const { return locus; }
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
+ const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+
+ // TODO: would a "vis_type" be better?
+ std::unique_ptr<Type> &get_type ()
+ {
+ rust_assert (param_type != nullptr);
+ return param_type;
+ }
};
/* A function pointer type - can be created via coercion from function items and
@@ -751,6 +811,7 @@ class BareFunctionType : public TypeNoBounds
FunctionQualifiers function_qualifiers;
std::vector<MaybeNamedParam> params;
bool is_variadic;
+ std::vector<Attribute> variadic_attrs;
// bool has_return_type;
// BareFunctionReturnType return_type;
@@ -768,21 +829,29 @@ public:
BareFunctionType (std::vector<LifetimeParam> lifetime_params,
FunctionQualifiers qualifiers,
std::vector<MaybeNamedParam> named_params, bool is_variadic,
+ std::vector<Attribute> variadic_attrs,
std::unique_ptr<TypeNoBounds> type, Location locus)
: for_lifetimes (std::move (lifetime_params)),
function_qualifiers (std::move (qualifiers)),
params (std::move (named_params)), is_variadic (is_variadic),
+ variadic_attrs (std::move (variadic_attrs)),
return_type (std::move (type)), locus (locus)
- {}
+ {
+ if (!variadic_attrs.empty ())
+ is_variadic = true;
+ }
// Copy constructor with clone
BareFunctionType (BareFunctionType const &other)
: for_lifetimes (other.for_lifetimes),
function_qualifiers (other.function_qualifiers), params (other.params),
- is_variadic (other.is_variadic),
- return_type (other.return_type->clone_type_no_bounds ()),
+ is_variadic (other.is_variadic), variadic_attrs (other.variadic_attrs),
locus (other.locus)
- {}
+ {
+ // guard to prevent null dereference
+ if (other.return_type != nullptr)
+ return_type = other.return_type->clone_type_no_bounds ();
+ }
// Overload assignment operator to deep copy
BareFunctionType &operator= (BareFunctionType const &other)
@@ -791,9 +860,15 @@ public:
function_qualifiers = other.function_qualifiers;
params = other.params;
is_variadic = other.is_variadic;
- return_type = other.return_type->clone_type_no_bounds ();
+ variadic_attrs = other.variadic_attrs;
locus = other.locus;
+ // guard to prevent null dereference
+ if (other.return_type != nullptr)
+ return_type = other.return_type->clone_type_no_bounds ();
+ else
+ return_type = nullptr;
+
return *this;
}
@@ -804,17 +879,25 @@ public:
std::string as_string () const override;
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final override { return get_locus (); }
void accept_vis (ASTVisitor &vis) override;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- BareFunctionType *clone_type_impl () const override
+ // TODO: this mutable getter seems kinda dodgy
+ std::vector<MaybeNamedParam> &get_function_params () { return params; }
+ const std::vector<MaybeNamedParam> &get_function_params () const
{
- return new BareFunctionType (*this);
+ return params;
+ }
+
+ // TODO: would a "vis_type" be better?
+ std::unique_ptr<TypeNoBounds> &get_return_type ()
+ {
+ rust_assert (has_return_type ());
+ return return_type;
}
+protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
BareFunctionType *clone_type_no_bounds_impl () const override
diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc
index 820f880..300240f 100644
--- a/gcc/rust/backend/rust-compile.cc
+++ b/gcc/rust/backend/rust-compile.cc
@@ -88,23 +88,23 @@ bool
Compilation::compileVarDecl (Bfunction *fndecl, AST::LetStmt *stmt,
std::vector<Bvariable *> &vars)
{
- AST::Type *type = stmt->has_type () ? stmt->type.get () : stmt->inferedType;
+ AST::Type *type = stmt->has_type () ? stmt->get_type ().get () : stmt->inferedType;
translatedType = NULL;
type->accept_vis (*this);
if (translatedType == NULL)
{
- rust_error_at (stmt->locus, "failed to compile type for var decl");
+ rust_error_at (stmt->get_locus (), "failed to compile type for var decl");
return false;
}
- stmt->variables_pattern->accept_vis (*this);
+ stmt->get_pattern ()->accept_vis (*this);
for (auto &pattern : patternBuffer)
{
- auto var = backend->local_variable (fndecl, pattern.variable_ident,
+ auto var = backend->local_variable (fndecl, pattern.get_ident (),
translatedType, NULL /*decl_var*/,
- false /*address_taken*/, stmt->locus);
+ false /*address_taken*/, stmt->get_locus ());
vars.push_back (var);
- scope.InsertVar (pattern.variable_ident, var);
+ scope.InsertVar (pattern.get_ident (), var);
}
patternBuffer.clear ();
return true;
@@ -173,10 +173,10 @@ Compilation::visit (AST::IdentifierExpr &ident_expr)
Bvariable *var = NULL;
if (!scope.LookupVar (ident_expr.as_string (), &var))
{
- rust_fatal_error (ident_expr.locus, "unknown var");
+ rust_fatal_error (ident_expr.get_locus (), "unknown var");
return;
}
- exprs.push_back (backend->var_expression (var, ident_expr.locus));
+ exprs.push_back (backend->var_expression (var, ident_expr.get_locus ()));
}
void
@@ -199,7 +199,7 @@ Compilation::visit (AST::PathInExpression &path)
if (scope.LookupFunction (path.as_string (), &fn))
{
auto expr
- = backend->function_code_expression (fn, path.get_locus_slow ());
+ = backend->function_code_expression (fn, path.get_locus ());
exprs.push_back (expr);
translatedType = scope.GetFnRetType (fn);
return;
@@ -219,16 +219,16 @@ Compilation::visit (AST::TypePathSegmentFunction &segment)
void
Compilation::visit (AST::TypePath &path)
{
- if (path.segments.size () > 1)
+ if (path.get_segments ().size () > 1)
{
- rust_error_at (path.locus, "unable to compile multi segment types yet");
+ rust_error_at (path.get_locus (), "unable to compile multi segment types yet");
return;
}
Btype *type = NULL;
if (!scope.LookupType (path.as_string (), &type))
{
- rust_error_at (path.locus, "unknown type");
+ rust_error_at (path.get_locus (), "unknown type");
return;
}
translatedType = type;
@@ -246,7 +246,7 @@ void
Compilation::visit (AST::LiteralExpr &expr)
{
Bexpression *compiled;
- switch (expr.literal.get_lit_type ())
+ switch (expr.get_lit_type ())
{
case AST::Literal::BOOL:
compiled = compileBooleanLiteral (expr.as_string ());
@@ -254,16 +254,16 @@ Compilation::visit (AST::LiteralExpr &expr)
case AST::Literal::FLOAT:
compiled
- = compileFloatLiteral (expr.as_string (), expr.get_locus_slow ());
+ = compileFloatLiteral (expr.as_string (), expr.get_locus ());
break;
case AST::Literal::INT:
compiled
- = compileIntegerLiteral (expr.as_string (), expr.get_locus_slow ());
+ = compileIntegerLiteral (expr.as_string (), expr.get_locus ());
break;
default:
- rust_fatal_error (expr.get_locus_slow (), "unknown literal");
+ rust_fatal_error (expr.get_locus (), "unknown literal");
return;
}
@@ -293,16 +293,16 @@ void
Compilation::visit (AST::NegationExpr &expr)
{
Bexpression *root = NULL;
- VISIT_POP (expr.get_expr ()->get_locus_slow (), expr.get_expr (), root,
+ VISIT_POP (expr.get_negated_expr ()->get_locus_slow (), expr.get_negated_expr ().get (), root,
exprs);
if (root == NULL)
{
- rust_error_at (expr.get_expr ()->get_locus_slow (), "failed to compile");
+ rust_error_at (expr.get_negated_expr ()->get_locus_slow (), "failed to compile");
return;
}
Operator op;
- switch (expr.negation_type)
+ switch (expr.get_negation_type ())
{
case AST::NegationExpr::NEGATE:
op = OPERATOR_MINUS;
@@ -311,11 +311,11 @@ Compilation::visit (AST::NegationExpr &expr)
op = OPERATOR_NOT;
break;
default:
- rust_fatal_error (expr.get_locus_slow (), "failed to compile operator");
+ rust_fatal_error (expr.get_locus (), "failed to compile operator");
return;
}
- auto unary = backend->unary_expression (op, root, expr.get_locus_slow ());
+ auto unary = backend->unary_expression (op, root, expr.get_locus ());
exprs.push_back (unary);
}
@@ -323,23 +323,23 @@ void
Compilation::visit (AST::ArithmeticOrLogicalExpr &expr)
{
Bexpression *lhs = NULL;
- VISIT_POP (expr.get_lhs ()->get_locus_slow (), expr.get_lhs (), lhs, exprs);
+ VISIT_POP (expr.get_left_expr ()->get_locus_slow (), expr.get_left_expr ().get (), lhs, exprs);
if (lhs == NULL)
{
- rust_error_at (expr.get_lhs ()->get_locus_slow (), "failed to compile");
+ rust_error_at (expr.get_left_expr ()->get_locus_slow (), "failed to compile");
return;
}
Bexpression *rhs = NULL;
- VISIT_POP (expr.right_expr->get_locus_slow (), expr.right_expr, rhs, exprs);
+ VISIT_POP (expr.get_right_expr ()->get_locus_slow (), expr.get_right_expr ().get (), rhs, exprs);
if (rhs == NULL)
{
- rust_error_at (expr.right_expr->get_locus_slow (), "failed to compile");
+ rust_error_at (expr.get_right_expr ()->get_locus_slow (), "failed to compile");
return;
}
Operator op;
- switch (expr.expr_type)
+ switch (expr.get_expr_type ())
{
case AST::ArithmeticOrLogicalExpr::ADD:
op = OPERATOR_PLUS;
@@ -372,12 +372,12 @@ Compilation::visit (AST::ArithmeticOrLogicalExpr &expr)
op = OPERATOR_RSHIFT;
break;
default:
- rust_fatal_error (expr.get_locus_slow (), "failed to compile operator");
+ rust_fatal_error (expr.get_locus (), "failed to compile operator");
return;
}
auto binExpr
- = backend->binary_expression (op, lhs, rhs, expr.get_locus_slow ());
+ = backend->binary_expression (op, lhs, rhs, expr.get_locus ());
exprs.push_back (binExpr);
}
@@ -385,23 +385,23 @@ void
Compilation::visit (AST::ComparisonExpr &expr)
{
Bexpression *lhs = NULL;
- VISIT_POP (expr.get_lhs ()->get_locus_slow (), expr.get_lhs (), lhs, exprs);
+ VISIT_POP (expr.get_left_expr ()->get_locus_slow (), expr.get_left_expr ().get (), lhs, exprs);
if (lhs == NULL)
{
- rust_error_at (expr.get_lhs ()->get_locus_slow (), "failed to compile");
+ rust_error_at (expr.get_left_expr ()->get_locus_slow (), "failed to compile");
return;
}
Bexpression *rhs = NULL;
- VISIT_POP (expr.right_expr->get_locus_slow (), expr.right_expr, rhs, exprs);
+ VISIT_POP (expr.get_right_expr ()->get_locus_slow (), expr.get_right_expr ().get (), rhs, exprs);
if (rhs == NULL)
{
- rust_error_at (expr.right_expr->get_locus_slow (), "failed to compile");
+ rust_error_at (expr.get_right_expr ()->get_locus_slow (), "failed to compile");
return;
}
Operator op;
- switch (expr.expr_type)
+ switch (expr.get_expr_type ())
{
case AST::ComparisonExpr::EQUAL:
op = OPERATOR_EQEQ;
@@ -422,12 +422,12 @@ Compilation::visit (AST::ComparisonExpr &expr)
op = OPERATOR_LE;
break;
default:
- rust_fatal_error (expr.get_locus_slow (), "failed to compile operator");
+ rust_fatal_error (expr.get_locus (), "failed to compile operator");
return;
}
auto compExpr
- = backend->binary_expression (op, lhs, rhs, expr.get_locus_slow ());
+ = backend->binary_expression (op, lhs, rhs, expr.get_locus ());
exprs.push_back (compExpr);
}
@@ -435,23 +435,23 @@ void
Compilation::visit (AST::LazyBooleanExpr &expr)
{
Bexpression *lhs = NULL;
- VISIT_POP (expr.get_lhs ()->get_locus_slow (), expr.get_lhs (), lhs, exprs);
+ VISIT_POP (expr.get_left_expr ()->get_locus_slow (), expr.get_left_expr ().get (), lhs, exprs);
if (lhs == NULL)
{
- rust_error_at (expr.get_lhs ()->get_locus_slow (), "failed to compile");
+ rust_error_at (expr.get_left_expr ()->get_locus_slow (), "failed to compile");
return;
}
Bexpression *rhs = NULL;
- VISIT_POP (expr.right_expr->get_locus_slow (), expr.right_expr, rhs, exprs);
+ VISIT_POP (expr.get_right_expr ()->get_locus_slow (), expr.get_right_expr ().get (), rhs, exprs);
if (rhs == NULL)
{
- rust_error_at (expr.right_expr->get_locus_slow (), "failed to compile");
+ rust_error_at (expr.get_right_expr ()->get_locus_slow (), "failed to compile");
return;
}
Operator op;
- switch (expr.expr_type)
+ switch (expr.get_expr_type ())
{
case AST::LazyBooleanExpr::LOGICAL_OR:
op = OPERATOR_OROR;
@@ -460,12 +460,12 @@ Compilation::visit (AST::LazyBooleanExpr &expr)
op = OPERATOR_ANDAND;
break;
default:
- rust_fatal_error (expr.get_locus_slow (), "failed to compile operator");
+ rust_fatal_error (expr.get_locus (), "failed to compile operator");
return;
}
auto compExpr
- = backend->binary_expression (op, lhs, rhs, expr.get_locus_slow ());
+ = backend->binary_expression (op, lhs, rhs, expr.get_locus ());
exprs.push_back (compExpr);
}
@@ -477,23 +477,23 @@ void
Compilation::visit (AST::AssignmentExpr &expr)
{
Bexpression *lhs = NULL;
- VISIT_POP (expr.get_lhs ()->get_locus_slow (), expr.get_lhs (), lhs, exprs);
+ VISIT_POP (expr.get_left_expr ()->get_locus_slow (), expr.get_left_expr ().get (), lhs, exprs);
if (lhs == NULL)
{
- rust_error_at (expr.get_lhs ()->get_locus_slow (), "failed to compile");
+ rust_error_at (expr.get_left_expr ()->get_locus_slow (), "failed to compile");
return;
}
Bexpression *rhs = NULL;
- VISIT_POP (expr.right_expr->get_locus_slow (), expr.right_expr, rhs, exprs);
+ VISIT_POP (expr.get_right_expr ()->get_locus_slow (), expr.get_right_expr ().get (), rhs, exprs);
if (rhs == NULL)
{
- rust_error_at (expr.right_expr->get_locus_slow (), "failed to compile");
+ rust_error_at (expr.get_right_expr ()->get_locus_slow (), "failed to compile");
return;
}
auto s = backend->assignment_statement (scope.GetCurrentFndecl (), lhs, rhs,
- expr.get_locus_slow ());
+ expr.get_locus ());
scope.AddStatement (s);
}
@@ -550,7 +550,7 @@ Compilation::visit (AST::ArrayExpr &expr)
translatedType = nullptr;
auto before = arrayConsStack.size ();
- expr.get_internal_elements ()->accept_vis (*this);
+ expr.get_array_elems ()->accept_vis (*this);
if (arrayConsStack.size () <= before)
{
rust_error_at (expr.get_locus_slow (),
@@ -617,10 +617,10 @@ void
Compilation::visit (AST::StructExprFieldIdentifierValue &field)
{
Bexpression *value = NULL;
- VISIT_POP (field.value->get_locus_slow (), field.value.get (), value, exprs);
+ VISIT_POP (field.get_value ()->get_locus_slow (), field.get_value ().get (), value, exprs);
if (value == NULL)
{
- rust_fatal_error (field.value->get_locus_slow (),
+ rust_fatal_error (field.get_value ()->get_locus_slow (),
"failed to compile value to struct");
return;
}
@@ -631,10 +631,10 @@ void
Compilation::visit (AST::StructExprFieldIndexValue &field)
{
Bexpression *value = NULL;
- VISIT_POP (field.value->get_locus_slow (), field.value.get (), value, exprs);
+ VISIT_POP (field.get_value ()->get_locus_slow (), field.get_value ().get (), value, exprs);
if (value == NULL)
{
- rust_fatal_error (field.value->get_locus_slow (),
+ rust_fatal_error (field.get_value ()->get_locus_slow (),
"failed to compile value to struct");
return;
}
@@ -647,14 +647,14 @@ Compilation::visit (AST::StructExprStructFields &expr)
AST::StructStruct *decl = NULL;
if (!scope.LookupStructDecl (expr.get_struct_name ().as_string (), &decl))
{
- rust_error_at (expr.get_locus_slow (), "unknown type");
+ rust_error_at (expr.get_locus (), "unknown type");
return;
}
Btype *structType = NULL;
if (!scope.LookupType (expr.get_struct_name ().as_string (), &structType))
{
- rust_fatal_error (expr.get_locus_slow (), "unknown type");
+ rust_fatal_error (expr.get_locus (), "unknown type");
return;
}
@@ -663,13 +663,13 @@ Compilation::visit (AST::StructExprStructFields &expr)
// FIXME type resolution pass should ensures these are in correct order
// and have defaults if required
- for (auto &field : expr.fields)
+ for (auto &field : expr.get_fields ())
{
Bexpression *value = NULL;
- VISIT_POP (expr.get_locus_slow (), field, value, exprs);
+ VISIT_POP (expr.get_locus (), field, value, exprs);
if (value == NULL)
{
- rust_fatal_error (expr.get_locus_slow (),
+ rust_fatal_error (expr.get_locus (),
"failed to compile value to struct");
return;
}
@@ -679,7 +679,7 @@ Compilation::visit (AST::StructExprStructFields &expr)
structBuffer.pop_back ();
auto cons = backend->constructor_expression (structType, constructor,
- expr.get_locus_slow ());
+ expr.get_locus ());
exprs.push_back (cons);
}
@@ -716,15 +716,15 @@ void
Compilation::visit (AST::CallExpr &expr)
{
Bexpression *fn = NULL;
- VISIT_POP (expr.function->get_locus_slow (), expr.function, fn, exprs);
+ VISIT_POP (expr.get_function_expr ()->get_locus_slow (), expr.get_function_expr (), fn, exprs);
if (fn == NULL)
{
- rust_error_at (expr.function->get_locus_slow (), "failed to resolve");
+ rust_error_at (expr.get_function_expr ()->get_locus_slow (), "failed to resolve");
return;
}
std::vector<Bexpression *> args;
- for (auto &param : expr.params)
+ for (auto &param : expr.get_params ())
{
Bexpression *arg = NULL;
VISIT_POP (param->get_locus_slow (), param, arg, exprs);
@@ -739,7 +739,7 @@ Compilation::visit (AST::CallExpr &expr)
}
auto call = backend->call_expression (scope.GetCurrentFndecl (), fn, args,
- NULL, expr.locus);
+ NULL, expr.get_locus ());
exprs.push_back (call);
}
@@ -766,7 +766,7 @@ Compilation::visit (AST::BlockExpr &expr)
start_location, end_location);
scope.PushBlock (code_block);
- for (auto &stmt : expr.statements)
+ for (auto &stmt : expr.get_statements ())
{
stmt->accept_vis (*this);
}
@@ -805,10 +805,10 @@ void
Compilation::visit (AST::ReturnExpr &expr)
{
Bexpression *ret = NULL;
- VISIT_POP (expr.get_expr ()->get_locus_slow (), expr.get_expr (), ret, exprs);
+ VISIT_POP (expr.get_returned_expr ()->get_locus_slow (), expr.get_returned_expr ().get (), ret, exprs);
if (ret == NULL)
{
- rust_fatal_error (expr.get_expr ()->get_locus_slow (),
+ rust_fatal_error (expr.get_returned_expr ()->get_locus_slow (),
"failed to compile");
return;
}
@@ -843,11 +843,11 @@ void
Compilation::visit (AST::IfExpr &expr)
{
Bexpression *cond = NULL;
- VISIT_POP (expr.get_if_condition ()->get_locus_slow (),
- expr.get_if_condition (), cond, exprs);
+ VISIT_POP (expr.get_condition_expr ()->get_locus_slow (),
+ expr.get_condition_expr ().get (), cond, exprs);
if (cond == NULL)
{
- rust_error_at (expr.get_if_condition ()->get_locus_slow (),
+ rust_error_at (expr.get_condition_expr ()->get_locus_slow (),
"failed to compile");
return;
}
@@ -856,7 +856,7 @@ Compilation::visit (AST::IfExpr &expr)
Bblock *then_block = scope.PopBlock ();
auto stmt = backend->if_statement (scope.GetCurrentFndecl (), cond,
- then_block, NULL, expr.get_locus_slow ());
+ then_block, NULL, expr.get_locus ());
stmts.push_back (stmt);
}
@@ -864,11 +864,11 @@ void
Compilation::visit (AST::IfExprConseqElse &expr)
{
Bexpression *cond = NULL;
- VISIT_POP (expr.get_if_condition ()->get_locus_slow (),
- expr.get_if_condition (), cond, exprs);
+ VISIT_POP (expr.get_condition_expr ()->get_locus_slow (),
+ expr.get_condition_expr ().get (), cond, exprs);
if (cond == NULL)
{
- rust_error_at (expr.get_if_condition ()->get_locus_slow (),
+ rust_error_at (expr.get_condition_expr ()->get_locus_slow (),
"failed to compile");
return;
}
@@ -881,7 +881,7 @@ Compilation::visit (AST::IfExprConseqElse &expr)
auto stmt
= backend->if_statement (scope.GetCurrentFndecl (), cond, then_block,
- else_block, expr.get_locus_slow ());
+ else_block, expr.get_locus ());
stmts.push_back (stmt);
}
@@ -889,11 +889,11 @@ void
Compilation::visit (AST::IfExprConseqIf &expr)
{
Bexpression *cond = NULL;
- VISIT_POP (expr.get_if_condition ()->get_locus_slow (),
- expr.get_if_condition (), cond, exprs);
+ VISIT_POP (expr.get_condition_expr ()->get_locus_slow (),
+ expr.get_condition_expr ().get (), cond, exprs);
if (cond == NULL)
{
- rust_error_at (expr.get_if_condition ()->get_locus_slow (),
+ rust_error_at (expr.get_condition_expr ()->get_locus_slow (),
"failed to compile");
return;
}
@@ -921,7 +921,7 @@ Compilation::visit (AST::IfExprConseqIf &expr)
auto stmt
= backend->if_statement (scope.GetCurrentFndecl (), cond, then_block,
- else_block, expr.get_locus_slow ());
+ else_block, expr.get_locus ());
stmts.push_back (stmt);
}
@@ -1014,22 +1014,22 @@ Compilation::visit (AST::Function &function)
std::vector<Backend::Btyped_identifier> parameters;
std::vector<Backend::Btyped_identifier> results;
- for (auto &param : function.function_params)
+ for (auto &param : function.get_function_params ())
{
// translate the type
translatedType = NULL;
- param.type->accept_vis (*this);
+ param.get_type ()->accept_vis (*this);
if (translatedType == NULL)
{
- rust_error_at (param.locus, "failed to generate type for parameter");
+ rust_error_at (param.get_locus (), "failed to generate type for parameter");
return;
}
auto before = patternBuffer.size ();
- param.param_name->accept_vis (*this);
+ param.get_pattern ()->accept_vis (*this);
if (patternBuffer.size () <= before)
{
- rust_error_at (param.locus, "failed to analyse parameter name");
+ rust_error_at (param.get_locus (), "failed to analyse parameter name");
return;
}
@@ -1039,19 +1039,19 @@ Compilation::visit (AST::Function &function)
auto paramName = patternBuffer.back ();
patternBuffer.pop_back ();
parameters.push_back (
- Backend::Btyped_identifier (paramName.variable_ident,
- translatedType, param.locus));
+ Backend::Btyped_identifier (paramName.get_ident (),
+ translatedType, param.get_locus ()));
}
}
Btype *returnType = NULL;
- if (function.has_function_return_type ())
+ if (function.has_return_type ())
{
translatedType = NULL;
- function.return_type->accept_vis (*this);
+ function.get_return_type ()->accept_vis (*this);
if (translatedType == NULL)
{
- rust_fatal_error (function.locus,
+ rust_fatal_error (function.get_locus (),
"failed to generate type for function");
return;
}
@@ -1063,12 +1063,12 @@ Compilation::visit (AST::Function &function)
}
Btype *fntype = backend->function_type (receiver, parameters, results, NULL,
- function.locus);
+ function.get_locus ());
Bfunction *fndecl
- = backend->function (fntype, function.function_name, "" /* asm_name */,
- 0 /* flags */, function.locus);
+ = backend->function (fntype, function.get_function_name (), "" /* asm_name */,
+ 0 /* flags */, function.get_locus ());
- scope.InsertFunction (function.function_name, fndecl, returnType);
+ scope.InsertFunction (function.get_function_name (), fndecl, returnType);
scope.Push ();
// setup the params
@@ -1085,7 +1085,7 @@ Compilation::visit (AST::Function &function)
if (!backend->function_set_parameters (fndecl, param_vars))
{
- rust_error_at (function.locus, "failed to setup parameter variables");
+ rust_error_at (function.get_locus (), "failed to setup parameter variables");
return;
}
@@ -1094,7 +1094,7 @@ Compilation::visit (AST::Function &function)
{
if (!compileVarDecl (fndecl, decl, vars))
{
- rust_error_at (decl->locus, "failed to compile var decl");
+ rust_error_at (decl->get_locus (), "failed to compile var decl");
return;
}
}
@@ -1102,12 +1102,12 @@ Compilation::visit (AST::Function &function)
// is null for top level functions - nested functions will have an enclosing
// scope
Bblock *enclosingScope = NULL;
- Location start_location = function.locus;
+ Location start_location = function.get_locus ();
Location end_location;
- if (function.function_body->statements.size () > 0)
+ if (function.get_definition ()->get_statements ().size () > 0)
{
end_location
- = function.function_body->statements.back ()->get_locus_slow ();
+ = function.get_definition ()->get_statements ().back ()->get_locus_slow ();
}
auto code_block = backend->block (fndecl, enclosingScope, vars,
@@ -1116,19 +1116,19 @@ Compilation::visit (AST::Function &function)
scope.PushBlock (code_block);
Bvariable *retDecl = NULL;
- if (function.has_function_return_type ())
+ if (function.has_return_type ())
{
bool address_is_taken = false;
Bstatement *ret_var_stmt = NULL;
retDecl = backend->temporary_variable (fndecl, code_block, returnType,
NULL, address_is_taken,
- function.locus, &ret_var_stmt);
+ function.get_locus (), &ret_var_stmt);
scope.AddStatement (ret_var_stmt);
}
- scope.PushCurrentFunction (function.function_name, fndecl, returnType,
+ scope.PushCurrentFunction (function.get_function_name (), fndecl, returnType,
retDecl);
- for (auto &stmt : function.function_body->statements)
+ for (auto &stmt : function.get_definition ()->get_statements ())
stmt->accept_vis (*this);
scope.PopBlock ();
@@ -1136,7 +1136,7 @@ Compilation::visit (AST::Function &function)
auto body = backend->block_statement (code_block);
if (!backend->function_set_body (fndecl, body))
{
- rust_error_at (function.locus, "failed to set body to function");
+ rust_error_at (function.get_locus (), "failed to set body to function");
return;
}
@@ -1154,36 +1154,36 @@ void
Compilation::visit (AST::StructStruct &struct_item)
{
std::vector<Backend::Btyped_identifier> fields;
- for (auto &field : struct_item.fields)
+ for (auto &field : struct_item.get_fields ())
{
translatedType = NULL;
- field.field_type->accept_vis (*this);
+ field.get_field_type ()->accept_vis (*this);
if (translatedType == NULL)
{
rust_fatal_error (
- struct_item.locus /* StructField is mi sing locus */,
+ struct_item.get_locus () /* StructField is mi sing locus */,
"failed to compile struct field");
return;
}
fields.push_back (Backend::Btyped_identifier (
- field.field_name, translatedType,
- struct_item.locus /* StructField is mi sing locus */));
+ field.get_field_name (), translatedType,
+ struct_item.get_locus () /* StructField is mi sing locus */));
}
auto compiledStruct
- = backend->placeholder_struct_type (struct_item.struct_name,
- struct_item.locus);
+ = backend->placeholder_struct_type (struct_item.get_struct_name (),
+ struct_item.get_locus ());
bool ok = backend->set_placeholder_struct_type (compiledStruct, fields);
if (!ok)
{
- rust_fatal_error (struct_item.locus, "failed to compile struct");
+ rust_fatal_error (struct_item.get_locus (), "failed to compile struct");
return;
}
type_decls.push_back (compiledStruct);
- scope.InsertType (struct_item.struct_name, compiledStruct);
- scope.InsertStructDecl (struct_item.struct_name, &struct_item);
+ scope.InsertType (struct_item.get_struct_name (), compiledStruct);
+ scope.InsertStructDecl (struct_item.get_struct_name (), &struct_item);
}
void
@@ -1363,25 +1363,25 @@ Compilation::visit (AST::LetStmt &stmt)
if (!stmt.has_init_expr ())
return;
- stmt.variables_pattern->accept_vis (*this);
+ stmt.get_pattern ()->accept_vis (*this);
for (auto &pattern : patternBuffer)
{
Bvariable *var = NULL;
- if (!scope.LookupVar (pattern.variable_ident, &var))
+ if (!scope.LookupVar (pattern.get_ident (), &var))
{
- rust_error_at (stmt.locus, "failed to find var decl for %s",
- pattern.variable_ident.c_str ());
+ rust_error_at (stmt.get_locus (), "failed to find var decl for %s",
+ pattern.get_ident ().c_str ());
return;
}
varBuffer.push_back (var);
Bexpression *init = NULL;
- VISIT_POP (stmt.init_expr->get_locus_slow (), stmt.init_expr, init,
+ VISIT_POP (stmt.get_init_expr ()->get_locus_slow (), stmt.get_init_expr (), init,
exprs);
if (init == NULL)
{
- rust_error_at (stmt.init_expr->get_locus_slow (),
+ rust_error_at (stmt.get_init_expr ()->get_locus_slow (),
"failed to compile init statement");
return;
}
@@ -1397,7 +1397,7 @@ Compilation::visit (AST::LetStmt &stmt)
void
Compilation::visit (AST::ExprStmtWithoutBlock &stmt)
{
- stmt.expr->accept_vis (*this);
+ stmt.get_expr ()->accept_vis (*this);
}
void
@@ -1413,7 +1413,7 @@ Compilation::visit (AST::ExprStmtWithBlock &stmt)
start_location, end_location);
scope.PushBlock (code_block);
- stmt.expr->accept_vis (*this);
+ stmt.get_expr ()->accept_vis (*this);
// get trailing if required
for (auto &s : stmts)
@@ -1465,7 +1465,7 @@ Compilation::visit (AST::ArrayType &type)
{
Btype *elementType;
translatedType = nullptr;
- type.get_element_type ()->accept_vis (*this);
+ type.get_elem_type ()->accept_vis (*this);
if (translatedType == nullptr)
{
rust_error_at (type.get_locus (),
diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc
index 8df1d1a..79e74ac 100644
--- a/gcc/rust/expand/rust-macro-expand.cc
+++ b/gcc/rust/expand/rust-macro-expand.cc
@@ -1,70 +1,3411 @@
#include "rust-macro-expand.h"
#include "rust-ast-full.h"
// is full really required?
+#include "rust-ast-visitor.h"
+#include "rust-diagnostics.h"
namespace Rust {
- void MacroExpander::expand_invoc(std::unique_ptr<AST::MacroInvocation>& invoc) {
- /* if current expansion depth > recursion limit, create an error (maybe fatal
- * error) and return */
-
- /* switch on type of macro:
- - '!' syntax macro (inner switch)
- - procedural macro - "A token-based function-like macro"
- - 'macro_rules' (by example/pattern-match) macro? or not? "an
- AST-based function-like macro"
- - else is unreachable
- - attribute syntax macro (inner switch)
- - procedural macro attribute syntax - "A token-based attribute macro"
- - legacy macro attribute syntax? - "an AST-based attribute macro"
- - non-macro attribute: mark known
- - else is unreachable
- - derive macro (inner switch)
- - derive or legacy derive - "token-based" vs "AST-based"
- - else is unreachable
- - derive container macro - unreachable*/
+// Visitor used to expand attributes.
+class AttrVisitor : public AST::ASTVisitor
+{
+private:
+ MacroExpander &expander;
+
+public:
+ AttrVisitor (MacroExpander &expander) : expander (expander) {}
+
+ void expand_struct_fields (std::vector<AST::StructField> &fields)
+ {
+ for (int i = 0; i < fields.size ();)
+ {
+ auto &field = fields[i];
+
+ auto &field_attrs = field.get_outer_attrs ();
+ expander.expand_cfg_attrs (field_attrs);
+ if (expander.fails_cfg (field_attrs))
+ {
+ fields.erase (fields.begin () + i);
+ continue;
+ }
+
+ // expand sub-types of type, but can't strip type itself
+ auto &type = field.get_field_type ();
+ type->accept_vis (*this);
+ if (type->is_marked_for_strip ())
+ rust_error_at (type->get_locus_slow (),
+ "cannot strip type in this position");
+
+ // if nothing else happens, increment
+ i++;
+ }
+ }
+
+ void expand_tuple_fields (std::vector<AST::TupleField> &fields)
+ {
+ for (int i = 0; i < fields.size ();)
+ {
+ auto &field = fields[i];
+
+ auto &field_attrs = field.get_outer_attrs ();
+ expander.expand_cfg_attrs (field_attrs);
+ if (expander.fails_cfg (field_attrs))
+ {
+ fields.erase (fields.begin () + i);
+ continue;
+ }
+
+ // expand sub-types of type, but can't strip type itself
+ auto &type = field.get_field_type ();
+ type->accept_vis (*this);
+ if (type->is_marked_for_strip ())
+ rust_error_at (type->get_locus_slow (),
+ "cannot strip type in this position");
+
+ // if nothing else happens, increment
+ i++;
+ }
+ }
+
+ void expand_function_params (std::vector<AST::FunctionParam> &params)
+ {
+ for (int i = 0; i < params.size ();)
+ {
+ auto &param = params[i];
+
+ auto &param_attrs = param.get_outer_attrs ();
+ expander.expand_cfg_attrs (param_attrs);
+ if (expander.fails_cfg (param_attrs))
+ {
+ params.erase (params.begin () + i);
+ continue;
+ }
+
+ // TODO: should an unwanted strip lead to break out of loop?
+ auto &pattern = param.get_pattern ();
+ pattern->accept_vis (*this);
+ if (pattern->is_marked_for_strip ())
+ rust_error_at (pattern->get_locus_slow (),
+ "cannot strip pattern in this position");
+
+ auto &type = param.get_type ();
+ type->accept_vis (*this);
+ if (type->is_marked_for_strip ())
+ rust_error_at (type->get_locus_slow (),
+ "cannot strip type in this position");
+
+ // increment
+ i++;
+ }
+ }
+
+ void expand_generic_args (AST::GenericArgs &args)
+ {
+ // lifetime args can't be expanded
+
+ // expand type args - strip sub-types only
+ for (auto &type : args.get_type_args ())
+ {
+ type->accept_vis (*this);
+ if (type->is_marked_for_strip ())
+ rust_error_at (type->get_locus_slow (),
+ "cannot strip type in this position");
+ }
+
+ // expand binding args - strip sub-types only
+ for (auto &binding : args.get_binding_args ())
+ {
+ auto &type = binding.get_type ();
+ type->accept_vis (*this);
+ if (type->is_marked_for_strip ())
+ rust_error_at (type->get_locus_slow (),
+ "cannot strip type in this position");
+ }
+ }
+
+ void expand_qualified_path_type (AST::QualifiedPathType &path_type)
+ {
+ auto &type = path_type.get_type ();
+ type->accept_vis (*this);
+ if (type->is_marked_for_strip ())
+ rust_error_at (type->get_locus_slow (),
+ "cannot strip type in this position");
+
+ if (path_type.has_as_clause ())
+ {
+ auto &type_path = path_type.get_as_type_path ();
+ visit (type_path);
+ if (type_path.is_marked_for_strip ())
+ rust_error_at (type_path.get_locus (),
+ "cannot strip type path in this position");
+ }
+ }
+
+ void expand_closure_params (std::vector<AST::ClosureParam> &params)
+ {
+ for (int i = 0; i < params.size ();)
+ {
+ auto &param = params[i];
+
+ auto &param_attrs = param.get_outer_attrs ();
+ expander.expand_cfg_attrs (param_attrs);
+ if (expander.fails_cfg (param_attrs))
+ {
+ params.erase (params.begin () + i);
+ continue;
+ }
+
+ auto &pattern = param.get_pattern ();
+ pattern->accept_vis (*this);
+ if (pattern->is_marked_for_strip ())
+ rust_error_at (pattern->get_locus_slow (),
+ "cannot strip pattern in this position");
+
+ if (param.has_type_given ())
+ {
+ auto &type = param.get_type ();
+ type->accept_vis (*this);
+ if (type->is_marked_for_strip ())
+ rust_error_at (type->get_locus_slow (),
+ "cannot strip type in this position");
+ }
+
+ // increment if found nothing else so far
+ i++;
+ }
+ }
+
+ void expand_self_param (AST::SelfParam &self_param)
+ {
+ if (self_param.has_type ())
+ {
+ auto &type = self_param.get_type ();
+ type->accept_vis (*this);
+ if (type->is_marked_for_strip ())
+ rust_error_at (type->get_locus_slow (),
+ "cannot strip type in this position");
+ }
+ // TODO: maybe check for invariants being violated - e.g. both type and
+ // lifetime?
+ }
+
+ void expand_where_clause (AST::WhereClause &where_clause)
+ {
+ // items cannot be stripped conceptually, so just accept visitor
+ for (auto &item : where_clause.get_items ())
+ item->accept_vis (*this);
+ }
+
+ void expand_trait_function_decl (AST::TraitFunctionDecl &decl)
+ {
+ // just expand sub-stuff - can't actually strip generic params themselves
+ for (auto &param : decl.get_generic_params ())
+ param->accept_vis (*this);
+
+ /* strip function parameters if required - this is specifically
+ * allowed by spec */
+ expand_function_params (decl.get_function_params ());
+
+ if (decl.has_return_type ())
+ {
+ auto &return_type = decl.get_return_type ();
+ return_type->accept_vis (*this);
+ if (return_type->is_marked_for_strip ())
+ rust_error_at (return_type->get_locus_slow (),
+ "cannot strip type in this position");
+ }
+
+ if (decl.has_where_clause ())
+ expand_where_clause (decl.get_where_clause ());
+ }
+
+ void expand_trait_method_decl (AST::TraitMethodDecl &decl)
+ {
+ // just expand sub-stuff - can't actually strip generic params themselves
+ for (auto &param : decl.get_generic_params ())
+ param->accept_vis (*this);
+
+ /* assuming you can't strip self param - wouldn't be a method
+ * anymore. spec allows outer attrs on self param, but doesn't
+ * specify whether cfg is used. */
+ expand_self_param (decl.get_self_param ());
+
+ /* strip function parameters if required - this is specifically
+ * allowed by spec */
+ expand_function_params (decl.get_function_params ());
+
+ if (decl.has_return_type ())
+ {
+ auto &return_type = decl.get_return_type ();
+ return_type->accept_vis (*this);
+ if (return_type->is_marked_for_strip ())
+ rust_error_at (return_type->get_locus_slow (),
+ "cannot strip type in this position");
+ }
+
+ if (decl.has_where_clause ())
+ expand_where_clause (decl.get_where_clause ());
+ }
+
+ void visit (AST::Token &) override
+ {
+ // shouldn't require?
+ }
+ void visit (AST::DelimTokenTree &) override
+ {
+ // shouldn't require?
+ }
+ void visit (AST::AttrInputMetaItemContainer &) override
+ {
+ // shouldn't require?
+ }
+ void visit (AST::IdentifierExpr &ident_expr) override
+ {
+ // strip test based on outer attrs
+ expander.expand_cfg_attrs (ident_expr.get_outer_attrs ());
+ if (expander.fails_cfg (ident_expr.get_outer_attrs ()))
+ {
+ ident_expr.mark_for_strip ();
+ return;
+ }
+ }
+ void visit (AST::Lifetime &) override
+ {
+ // shouldn't require?
+ }
+ void visit (AST::LifetimeParam &) override
+ {
+ // supposedly does not require - cfg does nothing
+ }
+ void visit (AST::MacroInvocationSemi &macro_invoc) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (macro_invoc.get_outer_attrs ());
+ if (expander.fails_cfg (macro_invoc.get_outer_attrs ()))
+ {
+ macro_invoc.mark_for_strip ();
+ return;
+ }
+
+ // can't strip simple path
+
+ // I don't think any macro token trees can be stripped in any way
+
+ // TODO: maybe have cfg! macro stripping behaviour here?
+ }
+
+ void visit (AST::PathInExpression &path) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (path.get_outer_attrs ());
+ if (expander.fails_cfg (path.get_outer_attrs ()))
+ {
+ path.mark_for_strip ();
+ return;
+ }
+
+ for (auto &segment : path.get_segments ())
+ {
+ if (segment.has_generic_args ())
+ expand_generic_args (segment.get_generic_args ());
+ }
+ }
+ void visit (AST::TypePathSegment &) override
+ {
+ // shouldn't require
+ }
+ void visit (AST::TypePathSegmentGeneric &segment) override
+ {
+ // TODO: strip inside generic args
+
+ if (!segment.has_generic_args ())
+ return;
+
+ expand_generic_args (segment.get_generic_args ());
+ }
+ void visit (AST::TypePathSegmentFunction &segment) override
+ {
+ auto &type_path_function = segment.get_type_path_function ();
+
+ for (auto &type : type_path_function.get_params ())
+ {
+ type->accept_vis (*this);
+ if (type->is_marked_for_strip ())
+ rust_error_at (type->get_locus_slow (),
+ "cannot strip type in this position");
+ }
+
+ if (type_path_function.has_return_type ())
+ {
+ auto &return_type = type_path_function.get_return_type ();
+ return_type->accept_vis (*this);
+ if (return_type->is_marked_for_strip ())
+ rust_error_at (return_type->get_locus_slow (),
+ "cannot strip type in this position");
+ }
+ }
+ void visit (AST::TypePath &path) override
+ {
+ // this shouldn't strip any segments, but can strip inside them
+ for (auto &segment : path.get_segments ())
+ segment->accept_vis (*this);
+ }
+ void visit (AST::QualifiedPathInExpression &path) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (path.get_outer_attrs ());
+ if (expander.fails_cfg (path.get_outer_attrs ()))
+ {
+ path.mark_for_strip ();
+ return;
+ }
+
+ expand_qualified_path_type (path.get_qualified_path_type ());
+
+ for (auto &segment : path.get_segments ())
+ {
+ if (segment.has_generic_args ())
+ expand_generic_args (segment.get_generic_args ());
+ }
+ }
+ void visit (AST::QualifiedPathInType &path) override
+ {
+ expand_qualified_path_type (path.get_qualified_path_type ());
+
+ // this shouldn't strip any segments, but can strip inside them
+ for (auto &segment : path.get_segments ())
+ segment->accept_vis (*this);
+ }
+
+ void visit (AST::LiteralExpr &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+ }
+ void visit (AST::AttrInputLiteral &) override
+ {
+ // shouldn't require?
+ }
+ void visit (AST::MetaItemLitExpr &) override
+ {
+ // shouldn't require?
+ }
+ void visit (AST::MetaItemPathLit &) override
+ {
+ // shouldn't require?
+ }
+ void visit (AST::BorrowExpr &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ /* strip any internal sub-expressions - expression itself isn't
+ * allowed to have external attributes in this position so can't be
+ * stripped. */
+ auto &borrowed_expr = expr.get_borrowed_expr ();
+ borrowed_expr->accept_vis (*this);
+ if (borrowed_expr->is_marked_for_strip ())
+ rust_error_at (borrowed_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::DereferenceExpr &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ /* strip any internal sub-expressions - expression itself isn't
+ * allowed to have external attributes in this position so can't be
+ * stripped. */
+ auto &dereferenced_expr = expr.get_dereferenced_expr ();
+ dereferenced_expr->accept_vis (*this);
+ if (dereferenced_expr->is_marked_for_strip ())
+ rust_error_at (dereferenced_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::ErrorPropagationExpr &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ /* strip any internal sub-expressions - expression itself isn't
+ * allowed to have external attributes in this position so can't be
+ * stripped. */
+ auto &propagating_expr = expr.get_propagating_expr ();
+ propagating_expr->accept_vis (*this);
+ if (propagating_expr->is_marked_for_strip ())
+ rust_error_at (propagating_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::NegationExpr &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ /* strip any internal sub-expressions - expression itself isn't
+ * allowed to have external attributes in this position so can't be
+ * stripped. */
+ auto &negated_expr = expr.get_negated_expr ();
+ negated_expr->accept_vis (*this);
+ if (negated_expr->is_marked_for_strip ())
+ rust_error_at (negated_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::ArithmeticOrLogicalExpr &expr) override
+ {
+ /* outer attributes never allowed before these. while cannot strip
+ * two direct descendant expressions, can strip ones below that */
+
+ /* should have no possibility for outer attrs as would be parsed
+ * with outer expr */
+ expr.get_left_expr ()->accept_vis (*this);
+ /* should syntactically not have outer attributes, though this may
+ * not have worked in practice */
+ expr.get_right_expr ()->accept_vis (*this);
+
+ // ensure that they are not marked for strip
+ if (expr.get_left_expr ()->is_marked_for_strip ())
+ rust_error_at (expr.get_left_expr ()->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes are never allowed "
+ "before binary op exprs");
+ if (expr.get_right_expr ()->is_marked_for_strip ())
+ rust_error_at (expr.get_right_expr ()->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::ComparisonExpr &expr) override
+ {
+ /* outer attributes never allowed before these. while cannot strip
+ * two direct descendant expressions, can strip ones below that */
+
+ /* should have no possibility for outer attrs as would be parsed
+ * with outer expr */
+ expr.get_left_expr ()->accept_vis (*this);
+ /* should syntactically not have outer attributes, though this may
+ * not have worked in practice */
+ expr.get_right_expr ()->accept_vis (*this);
+
+ // ensure that they are not marked for strip
+ if (expr.get_left_expr ()->is_marked_for_strip ())
+ rust_error_at (expr.get_left_expr ()->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes are never allowed "
+ "before binary op exprs");
+ if (expr.get_right_expr ()->is_marked_for_strip ())
+ rust_error_at (expr.get_right_expr ()->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::LazyBooleanExpr &expr) override
+ {
+ /* outer attributes never allowed before these. while cannot strip
+ * two direct descendant expressions, can strip ones below that */
+
+ /* should have no possibility for outer attrs as would be parsed
+ * with outer expr */
+ expr.get_left_expr ()->accept_vis (*this);
+ /* should syntactically not have outer attributes, though this may
+ * not have worked in practice */
+ expr.get_right_expr ()->accept_vis (*this);
+
+ // ensure that they are not marked for strip
+ if (expr.get_left_expr ()->is_marked_for_strip ())
+ rust_error_at (expr.get_left_expr ()->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes are never allowed "
+ "before binary op exprs");
+ if (expr.get_right_expr ()->is_marked_for_strip ())
+ rust_error_at (expr.get_right_expr ()->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::TypeCastExpr &expr) override
+ {
+ /* outer attributes never allowed before these. while cannot strip
+ * direct descendant expression, can strip ones below that */
+
+ auto &casted_expr = expr.get_casted_expr ();
+ /* should have no possibility for outer attrs as would be parsed
+ * with outer expr */
+ casted_expr->accept_vis (*this);
+
+ // ensure that they are not marked for strip
+ if (casted_expr->is_marked_for_strip ())
+ rust_error_at (casted_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes are never allowed before cast exprs");
+
+ // TODO: strip sub-types of type
+ auto &type = expr.get_type_to_cast_to ();
+ type->accept_vis (*this);
+ if (type->is_marked_for_strip ())
+ rust_error_at (type->get_locus_slow (),
+ "cannot strip type in this position");
+ }
+ void visit (AST::AssignmentExpr &expr) override
+ {
+ /* outer attributes never allowed before these. while cannot strip
+ * two direct descendant expressions, can strip ones below that */
+
+ /* should have no possibility for outer attrs as would be parsed
+ * with outer expr */
+ expr.get_left_expr ()->accept_vis (*this);
+ /* should syntactically not have outer attributes, though this may
+ * not have worked in practice */
+ expr.get_right_expr ()->accept_vis (*this);
+
+ // ensure that they are not marked for strip
+ if (expr.get_left_expr ()->is_marked_for_strip ())
+ rust_error_at (expr.get_left_expr ()->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes are never allowed "
+ "before binary op exprs");
+ if (expr.get_right_expr ()->is_marked_for_strip ())
+ rust_error_at (expr.get_right_expr ()->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::CompoundAssignmentExpr &expr) override
+ {
+ /* outer attributes never allowed before these. while cannot strip
+ * two direct descendant expressions, can strip ones below that */
+
+ /* should have no possibility for outer attrs as would be parsed
+ * with outer expr */
+ expr.get_left_expr ()->accept_vis (*this);
+ /* should syntactically not have outer attributes, though this may
+ * not have worked in practice */
+ expr.get_right_expr ()->accept_vis (*this);
+
+ // ensure that they are not marked for strip
+ if (expr.get_left_expr ()->is_marked_for_strip ())
+ rust_error_at (expr.get_left_expr ()->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes are never allowed "
+ "before binary op exprs");
+ if (expr.get_right_expr ()->is_marked_for_strip ())
+ rust_error_at (expr.get_right_expr ()->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::GroupedExpr &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ /* strip test based on inner attrs - spec says these are inner
+ * attributes, not outer attributes of inner expr */
+ expander.expand_cfg_attrs (expr.get_inner_attrs ());
+ if (expander.fails_cfg (expr.get_inner_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ /* strip any internal sub-expressions - expression itself isn't
+ * allowed to have external attributes in this position so can't be
+ * stripped. */
+ auto &inner_expr = expr.get_expr_in_parens ();
+ inner_expr->accept_vis (*this);
+ if (inner_expr->is_marked_for_strip ())
+ rust_error_at (inner_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::ArrayElemsValues &elems) override
+ {
+ /* apparently outer attributes are allowed in "elements of array
+ * expressions" according to spec */
+ auto &values = elems.get_values ();
+ for (int i = 0; i < values.size ();)
+ {
+ auto &value = values[i];
+
+ // mark for stripping if required
+ value->accept_vis (*this);
+
+ if (value->is_marked_for_strip ())
+ values.erase (values.begin () + i);
+ else
+ i++;
+ }
+ }
+ void visit (AST::ArrayElemsCopied &elems) override
+ {
+ /* apparently outer attributes are allowed in "elements of array
+ * expressions" according to spec. on the other hand, it would not
+ * make conceptual sense to be able to remove either expression. As
+ * such, not implementing. TODO clear up the ambiguity here */
+
+ // only intend stripping for internal sub-expressions
+ auto &copied_expr = elems.get_elem_to_copy ();
+ copied_expr->accept_vis (*this);
+ if (copied_expr->is_marked_for_strip ())
+ rust_error_at (copied_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+
+ auto &copy_count = elems.get_num_copies ();
+ copy_count->accept_vis (*this);
+ if (copy_count->is_marked_for_strip ())
+ rust_error_at (copy_count->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::ArrayExpr &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ /* strip test based on inner attrs - spec says there are separate
+ * inner attributes, not just outer attributes of inner exprs */
+ expander.expand_cfg_attrs (expr.get_inner_attrs ());
+ if (expander.fails_cfg (expr.get_inner_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ /* assuming you can't strip away the ArrayElems type, but can strip
+ * internal expressions and whatever */
+ if (expr.has_array_elems ())
+ expr.get_array_elems ()->accept_vis (*this);
+ }
+ void visit (AST::ArrayIndexExpr &expr) override
+ {
+ /* it is unclear whether outer attributes are supposed to be
+ * allowed, but conceptually it wouldn't make much sense, but
+ * having expansion code anyway. TODO */
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ /* strip any internal sub-expressions - expression itself isn't
+ * allowed to have external attributes in this position so can't be
+ * stripped. */
+ auto &array_expr = expr.get_array_expr ();
+ array_expr->accept_vis (*this);
+ if (array_expr->is_marked_for_strip ())
+ rust_error_at (array_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+
+ auto &index_expr = expr.get_index_expr ();
+ index_expr->accept_vis (*this);
+ if (index_expr->is_marked_for_strip ())
+ rust_error_at (index_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::TupleExpr &expr) override
+ {
+ /* according to spec, outer attributes are allowed on "elements of
+ * tuple expressions" */
+
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ /* strip test based on inner attrs - spec says these are inner
+ * attributes, not outer attributes of inner expr */
+ expander.expand_cfg_attrs (expr.get_inner_attrs ());
+ if (expander.fails_cfg (expr.get_inner_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ /* apparently outer attributes are allowed in "elements of tuple
+ * expressions" according to spec */
+ auto &values = expr.get_tuple_elems ();
+ for (int i = 0; i < values.size ();)
+ {
+ auto &value = values[i];
+
+ // mark for stripping if required
+ value->accept_vis (*this);
+
+ if (value->is_marked_for_strip ())
+ values.erase (values.begin () + i);
+ else
+ i++;
+ }
+ }
+ void visit (AST::TupleIndexExpr &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ /* wouldn't strip this directly (as outer attrs should be
+ * associated with this level), but any sub-expressions would be
+ * stripped. Thus, no need to erase when strip check called. */
+ auto &tuple_expr = expr.get_tuple_expr ();
+ tuple_expr->accept_vis (*this);
+ if (tuple_expr->is_marked_for_strip ())
+ rust_error_at (tuple_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::StructExprStruct &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ /* strip test based on inner attrs - spec says these are inner
+ * attributes, not outer attributes of inner expr */
+ expander.expand_cfg_attrs (expr.get_inner_attrs ());
+ if (expander.fails_cfg (expr.get_inner_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ // strip sub-exprs of path
+ auto &struct_name = expr.get_struct_name ();
+ visit (struct_name);
+ if (struct_name.is_marked_for_strip ())
+ rust_error_at (struct_name.get_locus (),
+ "cannot strip path in this position");
+ }
+ void visit (AST::StructExprFieldIdentifier &) override
+ {
+ // as no attrs (at moment, at least), no stripping possible
+ }
+ void visit (AST::StructExprFieldIdentifierValue &field) override
+ {
+ /* as no attrs possible (at moment, at least), only sub-expression
+ * stripping is possible */
+ auto &value = field.get_value ();
+ value->accept_vis (*this);
+ if (value->is_marked_for_strip ())
+ rust_error_at (value->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::StructExprFieldIndexValue &field) override
+ {
+ /* as no attrs possible (at moment, at least), only sub-expression
+ * stripping is possible */
+ auto &value = field.get_value ();
+ value->accept_vis (*this);
+ if (value->is_marked_for_strip ())
+ rust_error_at (value->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::StructExprStructFields &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ /* strip test based on inner attrs - spec says these are inner
+ * attributes, not outer attributes of inner expr */
+ expander.expand_cfg_attrs (expr.get_inner_attrs ());
+ if (expander.fails_cfg (expr.get_inner_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ // strip sub-exprs of path
+ auto &struct_name = expr.get_struct_name ();
+ visit (struct_name);
+ if (struct_name.is_marked_for_strip ())
+ rust_error_at (struct_name.get_locus (),
+ "cannot strip path in this position");
+
+ /* spec does not specify whether expressions are allowed to be
+ * stripped at top level of struct fields, but I wouldn't think
+ * that they would be, so operating under the assumption that only
+ * sub-expressions can be stripped. */
+ for (auto &field : expr.get_fields ())
+ {
+ field->accept_vis (*this);
+ // shouldn't strip in this
+ }
+
+ /* struct base presumably can't be stripped, as the '..' is before
+ * the expression. as such, can only strip sub-expressions. */
+ if (expr.has_struct_base ())
+ {
+ auto &base_struct_expr = expr.get_struct_base ().get_base_struct ();
+ base_struct_expr->accept_vis (*this);
+ if (base_struct_expr->is_marked_for_strip ())
+ rust_error_at (base_struct_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ }
+ void visit (AST::StructExprStructBase &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ /* strip test based on inner attrs - spec says these are inner
+ * attributes, not outer attributes of inner expr */
+ expander.expand_cfg_attrs (expr.get_inner_attrs ());
+ if (expander.fails_cfg (expr.get_inner_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ // strip sub-exprs of path
+ auto &struct_name = expr.get_struct_name ();
+ visit (struct_name);
+ if (struct_name.is_marked_for_strip ())
+ rust_error_at (struct_name.get_locus (),
+ "cannot strip path in this position");
+
+ /* struct base presumably can't be stripped, as the '..' is before
+ * the expression. as such, can only strip sub-expressions. */
+ rust_assert (!expr.get_struct_base ().is_invalid ());
+ auto &base_struct_expr = expr.get_struct_base ().get_base_struct ();
+ base_struct_expr->accept_vis (*this);
+ if (base_struct_expr->is_marked_for_strip ())
+ rust_error_at (base_struct_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::StructExprTuple &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ /* strip test based on inner attrs - spec says these are inner
+ * attributes, not outer attributes of inner expr */
+ expander.expand_cfg_attrs (expr.get_inner_attrs ());
+ if (expander.fails_cfg (expr.get_inner_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ // strip sub-exprs of path
+ auto &struct_name = expr.get_struct_name ();
+ visit (struct_name);
+ if (struct_name.is_marked_for_strip ())
+ rust_error_at (struct_name.get_locus (),
+ "cannot strip path in this position");
+
+ /* spec says outer attributes are specifically allowed for elements
+ * of tuple-style struct expressions, so full stripping possible */
+ auto &values = expr.get_elems ();
+ for (int i = 0; i < values.size ();)
+ {
+ auto &value = values[i];
+
+ // mark for stripping if required
+ value->accept_vis (*this);
+
+ if (value->is_marked_for_strip ())
+ values.erase (values.begin () + i);
+ else
+ i++;
+ }
+ }
+ void visit (AST::StructExprUnit &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ // strip sub-exprs of path
+ auto &struct_name = expr.get_struct_name ();
+ visit (struct_name);
+ if (struct_name.is_marked_for_strip ())
+ rust_error_at (struct_name.get_locus (),
+ "cannot strip path in this position");
+ }
+ void visit (AST::EnumExprFieldIdentifier &) override
+ {
+ // as no attrs (at moment, at least), no stripping possible
+ }
+ void visit (AST::EnumExprFieldIdentifierValue &field) override
+ {
+ /* as no attrs possible (at moment, at least), only sub-expression
+ * stripping is possible */
+ auto &value = field.get_value ();
+ value->accept_vis (*this);
+ if (value->is_marked_for_strip ())
+ rust_error_at (value->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::EnumExprFieldIndexValue &field) override
+ {
+ /* as no attrs possible (at moment, at least), only sub-expression
+ * stripping is possible */
+ auto &value = field.get_value ();
+ value->accept_vis (*this);
+ if (value->is_marked_for_strip ())
+ rust_error_at (value->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::EnumExprStruct &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ // supposedly spec doesn't allow inner attributes in enum exprs
+
+ // strip sub-exprs of path
+ auto &enum_path = expr.get_enum_variant_path ();
+ visit (enum_path);
+ if (enum_path.is_marked_for_strip ())
+ rust_error_at (enum_path.get_locus (),
+ "cannot strip path in this position");
+
+ /* spec does not specify whether expressions are allowed to be
+ * stripped at top level of expression fields, but I wouldn't think
+ * that they would be, so operating under the assumption that only
+ * sub-expressions can be stripped. */
+ for (auto &field : expr.get_fields ())
+ {
+ field->accept_vis (*this);
+ // shouldn't strip in this
+ }
+ }
+ void visit (AST::EnumExprTuple &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ // supposedly spec doesn't allow inner attributes in enum exprs
+
+ // strip sub-exprs of path
+ auto &enum_path = expr.get_enum_variant_path ();
+ visit (enum_path);
+ if (enum_path.is_marked_for_strip ())
+ rust_error_at (enum_path.get_locus (),
+ "cannot strip path in this position");
+
+ /* spec says outer attributes are specifically allowed for elements
+ * of tuple-style enum expressions, so full stripping possible */
+ auto &values = expr.get_elems ();
+ for (int i = 0; i < values.size ();)
+ {
+ auto &value = values[i];
+
+ // mark for stripping if required
+ value->accept_vis (*this);
+
+ if (value->is_marked_for_strip ())
+ values.erase (values.begin () + i);
+ else
+ i++;
+ }
+ }
+ void visit (AST::EnumExprFieldless &expr) override
+ {
+ // can't be stripped as no attrs
+
+ // strip sub-exprs of path
+ auto &enum_path = expr.get_enum_variant_path ();
+ visit (enum_path);
+ if (enum_path.is_marked_for_strip ())
+ rust_error_at (enum_path.get_locus (),
+ "cannot strip path in this position");
+ }
+ void visit (AST::CallExpr &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ /* should not be outer attrs on "function" expression - outer attrs
+ * should be associated with call expr as a whole. only sub-expr
+ * expansion is possible. */
+ auto &function = expr.get_function_expr ();
+ function->accept_vis (*this);
+ if (function->is_marked_for_strip ())
+ rust_error_at (function->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+
+ /* spec says outer attributes are specifically allowed for elements
+ * of call expressions, so full stripping possible */
+ auto &params = expr.get_params ();
+ for (int i = 0; i < params.size ();)
+ {
+ auto &param = params[i];
+
+ // mark for stripping if required
+ param->accept_vis (*this);
+
+ if (param->is_marked_for_strip ())
+ params.erase (params.begin () + i);
+ else
+ i++;
+ }
+ }
+ void visit (AST::MethodCallExpr &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ /* should not be outer attrs on "receiver" expression - outer attrs
+ * should be associated with call expr as a whole. only sub-expr
+ * expansion is possible. */
+ auto &receiver = expr.get_receiver_expr ();
+ receiver->accept_vis (*this);
+ if (receiver->is_marked_for_strip ())
+ rust_error_at (receiver->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+
+ auto &method_name = expr.get_method_name ();
+ if (method_name.has_generic_args ())
+ expand_generic_args (method_name.get_generic_args ());
+
+ /* spec says outer attributes are specifically allowed for elements
+ * of method call expressions, so full stripping possible */
+ auto &params = expr.get_params ();
+ for (int i = 0; i < params.size ();)
+ {
+ auto &param = params[i];
+
+ // mark for stripping if required
+ param->accept_vis (*this);
+
+ if (param->is_marked_for_strip ())
+ params.erase (params.begin () + i);
+ else
+ i++;
+ }
+ }
+ void visit (AST::FieldAccessExpr &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ /* should not be outer attrs on "receiver" expression - outer attrs
+ * should be associated with field expr as a whole. only sub-expr
+ * expansion is possible. */
+ auto &receiver = expr.get_receiver_expr ();
+ receiver->accept_vis (*this);
+ if (receiver->is_marked_for_strip ())
+ rust_error_at (receiver->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::ClosureExprInner &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ /* strip closure parameters if required - this is specifically
+ * allowed by spec */
+ expand_closure_params (expr.get_params ());
+
+ // can't strip expression itself, but can strip sub-expressions
+ auto &definition_expr = expr.get_definition_expr ();
+ definition_expr->accept_vis (*this);
+ if (definition_expr->is_marked_for_strip ())
+ rust_error_at (definition_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::BlockExpr &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ /* strip test based on inner attrs - spec says there are inner
+ * attributes, not just outer attributes of inner stmts */
+ expander.expand_cfg_attrs (expr.get_inner_attrs ());
+ if (expander.fails_cfg (expr.get_inner_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ // strip all statements
+ auto &stmts = expr.get_statements ();
+ for (int i = 0; i < stmts.size ();)
+ {
+ auto &stmt = stmts[i];
+
+ // mark for stripping if required
+ stmt->accept_vis (*this);
+
+ if (stmt->is_marked_for_strip ())
+ stmts.erase (stmts.begin () + i);
+ else
+ i++;
+ }
+
+ // strip tail expression if exists - can actually fully remove it
+ if (expr.has_tail_expr ())
+ {
+ auto &tail_expr = expr.get_tail_expr ();
+
+ tail_expr->accept_vis (*this);
+
+ if (tail_expr->is_marked_for_strip ())
+ expr.strip_tail_expr ();
+ }
+ }
+ void visit (AST::ClosureExprInnerTyped &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ /* strip closure parameters if required - this is specifically
+ * allowed by spec */
+ expand_closure_params (expr.get_params ());
+
+ // can't strip return type, but can strip sub-types
+ auto &type = expr.get_return_type ();
+ type->accept_vis (*this);
+ if (type->is_marked_for_strip ())
+ rust_error_at (type->get_locus_slow (),
+ "cannot strip type in this position");
+
+ // can't strip expression itself, but can strip sub-expressions
+ auto &definition_block = expr.get_definition_block ();
+ definition_block->accept_vis (*this);
+ if (definition_block->is_marked_for_strip ())
+ rust_error_at (definition_block->get_locus_slow (),
+ "cannot strip block expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::ContinueExpr &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+ }
+ void visit (AST::BreakExpr &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ /* spec does not say that you can have outer attributes on
+ * expression, so assuming you can't. stripping for sub-expressions
+ * is the only thing that can be done */
+ if (expr.has_break_expr ())
+ {
+ auto &break_expr = expr.get_break_expr ();
+
+ break_expr->accept_vis (*this);
+
+ if (break_expr->is_marked_for_strip ())
+ rust_error_at (break_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ }
+ void visit (AST::RangeFromToExpr &expr) override
+ {
+ /* outer attributes never allowed before these. while cannot strip
+ * two direct descendant expressions, can strip ones below that */
+
+ /* should have no possibility for outer attrs as would be parsed
+ * with outer expr */
+ expr.get_from_expr ()->accept_vis (*this);
+ /* should syntactically not have outer attributes, though this may
+ * not have worked in practice */
+ expr.get_to_expr ()->accept_vis (*this);
+
+ // ensure that they are not marked for strip
+ if (expr.get_from_expr ()->is_marked_for_strip ())
+ rust_error_at (expr.get_from_expr ()->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes are never allowed "
+ "before range exprs");
+ if (expr.get_to_expr ()->is_marked_for_strip ())
+ rust_error_at (expr.get_to_expr ()->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::RangeFromExpr &expr) override
+ {
+ /* outer attributes never allowed before these. while cannot strip
+ * direct descendant expression, can strip ones below that */
+
+ /* should have no possibility for outer attrs as would be parsed
+ * with outer expr */
+ auto &from_expr = expr.get_from_expr ();
+
+ from_expr->accept_vis (*this);
+
+ if (from_expr->is_marked_for_strip ())
+ rust_error_at (from_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes are never allowed before range exprs");
+ }
+ void visit (AST::RangeToExpr &expr) override
+ {
+ /* outer attributes never allowed before these. while cannot strip
+ * direct descendant expression, can strip ones below that */
+
+ /* should syntactically not have outer attributes, though this may
+ * not have worked in practice */
+ auto &to_expr = expr.get_to_expr ();
+
+ to_expr->accept_vis (*this);
+
+ if (to_expr->is_marked_for_strip ())
+ rust_error_at (to_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::RangeFullExpr &) override
+ {
+ // outer attributes never allowed before these, so no stripping
+ }
+ void visit (AST::RangeFromToInclExpr &expr) override
+ {
+ /* outer attributes never allowed before these. while cannot strip
+ * two direct descendant expressions, can strip ones below that */
+
+ /* should have no possibility for outer attrs as would be parsed
+ * with outer expr */
+ expr.get_from_expr ()->accept_vis (*this);
+ /* should syntactically not have outer attributes, though this may
+ * not have worked in practice */
+ expr.get_to_expr ()->accept_vis (*this);
+
+ // ensure that they are not marked for strip
+ if (expr.get_from_expr ()->is_marked_for_strip ())
+ rust_error_at (expr.get_from_expr ()->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes are never allowed "
+ "before range exprs");
+ if (expr.get_to_expr ()->is_marked_for_strip ())
+ rust_error_at (expr.get_to_expr ()->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::RangeToInclExpr &expr) override
+ {
+ /* outer attributes never allowed before these. while cannot strip
+ * direct descendant expression, can strip ones below that */
+
+ /* should syntactically not have outer attributes, though this may
+ * not have worked in practice */
+ auto &to_expr = expr.get_to_expr ();
+
+ to_expr->accept_vis (*this);
+
+ if (to_expr->is_marked_for_strip ())
+ rust_error_at (to_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::ReturnExpr &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ /* spec does not say that you can have outer attributes on
+ * expression, so assuming you can't. stripping for sub-expressions
+ * is the only thing that can be done */
+ if (expr.has_returned_expr ())
+ {
+ auto &returned_expr = expr.get_returned_expr ();
+
+ returned_expr->accept_vis (*this);
+
+ if (returned_expr->is_marked_for_strip ())
+ rust_error_at (returned_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ /* TODO: conceptually, you would maybe be able to remove a returned
+ * expr - e.g. if you had conditional compilation returning void or
+ * returning a type. On the other hand, I think that function
+ * return type cannot be conditionally compiled, so I assumed you
+ * can't do this either. */
+ }
+ void visit (AST::UnsafeBlockExpr &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ // can't strip block itself, but can strip sub-expressions
+ auto &block_expr = expr.get_block_expr ();
+ block_expr->accept_vis (*this);
+ if (block_expr->is_marked_for_strip ())
+ rust_error_at (block_expr->get_locus_slow (),
+ "cannot strip block expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::LoopExpr &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ // can't strip block itself, but can strip sub-expressions
+ auto &loop_block = expr.get_loop_block ();
+ loop_block->accept_vis (*this);
+ if (loop_block->is_marked_for_strip ())
+ rust_error_at (loop_block->get_locus_slow (),
+ "cannot strip block expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::WhileLoopExpr &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ // can't strip predicate expr itself, but can strip sub-expressions
+ auto &predicate_expr = expr.get_predicate_expr ();
+ predicate_expr->accept_vis (*this);
+ if (predicate_expr->is_marked_for_strip ())
+ rust_error_at (predicate_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+
+ // can't strip block itself, but can strip sub-expressions
+ auto &loop_block = expr.get_loop_block ();
+ loop_block->accept_vis (*this);
+ if (loop_block->is_marked_for_strip ())
+ rust_error_at (loop_block->get_locus_slow (),
+ "cannot strip block expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::WhileLetLoopExpr &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ for (auto &pattern : expr.get_patterns ())
+ {
+ pattern->accept_vis (*this);
+ if (pattern->is_marked_for_strip ())
+ rust_error_at (pattern->get_locus_slow (),
+ "cannot strip pattern in this position");
+ }
+
+ // can't strip scrutinee expr itself, but can strip sub-expressions
+ auto &scrutinee_expr = expr.get_scrutinee_expr ();
+ scrutinee_expr->accept_vis (*this);
+ if (scrutinee_expr->is_marked_for_strip ())
+ rust_error_at (scrutinee_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+
+ // can't strip block itself, but can strip sub-expressions
+ auto &loop_block = expr.get_loop_block ();
+ loop_block->accept_vis (*this);
+ if (loop_block->is_marked_for_strip ())
+ rust_error_at (loop_block->get_locus_slow (),
+ "cannot strip block expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::ForLoopExpr &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ // TODO: strip sub-patterns of pattern
+ auto &pattern = expr.get_pattern ();
+ pattern->accept_vis (*this);
+ if (pattern->is_marked_for_strip ())
+ rust_error_at (pattern->get_locus_slow (),
+ "cannot strip pattern in this position");
+
+ // can't strip scrutinee expr itself, but can strip sub-expressions
+ auto &iterator_expr = expr.get_iterator_expr ();
+ iterator_expr->accept_vis (*this);
+ if (iterator_expr->is_marked_for_strip ())
+ rust_error_at (iterator_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+
+ // can't strip block itself, but can strip sub-expressions
+ auto &loop_block = expr.get_loop_block ();
+ loop_block->accept_vis (*this);
+ if (loop_block->is_marked_for_strip ())
+ rust_error_at (loop_block->get_locus_slow (),
+ "cannot strip block expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::IfExpr &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ // can't strip condition expr itself, but can strip sub-expressions
+ auto &condition_expr = expr.get_condition_expr ();
+ condition_expr->accept_vis (*this);
+ if (condition_expr->is_marked_for_strip ())
+ rust_error_at (condition_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+
+ // can't strip if block itself, but can strip sub-expressions
+ auto &if_block = expr.get_if_block ();
+ if_block->accept_vis (*this);
+ if (if_block->is_marked_for_strip ())
+ rust_error_at (if_block->get_locus_slow (),
+ "cannot strip block expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::IfExprConseqElse &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ // can't strip condition expr itself, but can strip sub-expressions
+ auto &condition_expr = expr.get_condition_expr ();
+ condition_expr->accept_vis (*this);
+ if (condition_expr->is_marked_for_strip ())
+ rust_error_at (condition_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+
+ // can't strip if block itself, but can strip sub-expressions
+ auto &if_block = expr.get_if_block ();
+ if_block->accept_vis (*this);
+ if (if_block->is_marked_for_strip ())
+ rust_error_at (if_block->get_locus_slow (),
+ "cannot strip block expression in this position - outer "
+ "attributes not allowed");
+
+ // can't strip else block itself, but can strip sub-expressions
+ auto &else_block = expr.get_else_block ();
+ else_block->accept_vis (*this);
+ if (else_block->is_marked_for_strip ())
+ rust_error_at (else_block->get_locus_slow (),
+ "cannot strip block expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::IfExprConseqIf &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ // can't strip condition expr itself, but can strip sub-expressions
+ auto &condition_expr = expr.get_condition_expr ();
+ condition_expr->accept_vis (*this);
+ if (condition_expr->is_marked_for_strip ())
+ rust_error_at (condition_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+
+ // can't strip if block itself, but can strip sub-expressions
+ auto &if_block = expr.get_if_block ();
+ if_block->accept_vis (*this);
+ if (if_block->is_marked_for_strip ())
+ rust_error_at (if_block->get_locus_slow (),
+ "cannot strip block expression in this position - outer "
+ "attributes not allowed");
+
+ // can't strip if expr itself, but can strip sub-expressions
+ auto &conseq_if_expr = expr.get_conseq_if_expr ();
+ conseq_if_expr->accept_vis (*this);
+ if (conseq_if_expr->is_marked_for_strip ())
+ rust_error_at (conseq_if_expr->get_locus_slow (),
+ "cannot strip consequent if expression in this "
+ "position - outer attributes not allowed");
+ }
+ void visit (AST::IfExprConseqIfLet &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ // can't strip condition expr itself, but can strip sub-expressions
+ auto &condition_expr = expr.get_condition_expr ();
+ condition_expr->accept_vis (*this);
+ if (condition_expr->is_marked_for_strip ())
+ rust_error_at (condition_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+
+ // can't strip if block itself, but can strip sub-expressions
+ auto &if_block = expr.get_if_block ();
+ if_block->accept_vis (*this);
+ if (if_block->is_marked_for_strip ())
+ rust_error_at (if_block->get_locus_slow (),
+ "cannot strip block expression in this position - outer "
+ "attributes not allowed");
+
+ // can't strip if let expr itself, but can strip sub-expressions
+ auto &conseq_if_let_expr = expr.get_conseq_if_let_expr ();
+ conseq_if_let_expr->accept_vis (*this);
+ if (conseq_if_let_expr->is_marked_for_strip ())
+ rust_error_at (conseq_if_let_expr->get_locus_slow (),
+ "cannot strip consequent if let expression in this "
+ "position - outer attributes not "
+ "allowed");
+ }
+ void visit (AST::IfLetExpr &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ for (auto &pattern : expr.get_patterns ())
+ {
+ pattern->accept_vis (*this);
+ if (pattern->is_marked_for_strip ())
+ rust_error_at (pattern->get_locus_slow (),
+ "cannot strip pattern in this position");
+ }
+
+ // can't strip value expr itself, but can strip sub-expressions
+ auto &value_expr = expr.get_value_expr ();
+ value_expr->accept_vis (*this);
+ if (value_expr->is_marked_for_strip ())
+ rust_error_at (value_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+
+ // can't strip if block itself, but can strip sub-expressions
+ auto &if_block = expr.get_if_block ();
+ if_block->accept_vis (*this);
+ if (if_block->is_marked_for_strip ())
+ rust_error_at (if_block->get_locus_slow (),
+ "cannot strip block expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::IfLetExprConseqElse &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ for (auto &pattern : expr.get_patterns ())
+ {
+ pattern->accept_vis (*this);
+ if (pattern->is_marked_for_strip ())
+ rust_error_at (pattern->get_locus_slow (),
+ "cannot strip pattern in this position");
+ }
+
+ // can't strip value expr itself, but can strip sub-expressions
+ auto &value_expr = expr.get_value_expr ();
+ value_expr->accept_vis (*this);
+ if (value_expr->is_marked_for_strip ())
+ rust_error_at (value_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+
+ // can't strip if block itself, but can strip sub-expressions
+ auto &if_block = expr.get_if_block ();
+ if_block->accept_vis (*this);
+ if (if_block->is_marked_for_strip ())
+ rust_error_at (if_block->get_locus_slow (),
+ "cannot strip block expression in this position - outer "
+ "attributes not allowed");
+
+ // can't strip else block itself, but can strip sub-expressions
+ auto &else_block = expr.get_else_block ();
+ else_block->accept_vis (*this);
+ if (else_block->is_marked_for_strip ())
+ rust_error_at (else_block->get_locus_slow (),
+ "cannot strip block expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::IfLetExprConseqIf &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ for (auto &pattern : expr.get_patterns ())
+ {
+ pattern->accept_vis (*this);
+ if (pattern->is_marked_for_strip ())
+ rust_error_at (pattern->get_locus_slow (),
+ "cannot strip pattern in this position");
+ }
+
+ // can't strip value expr itself, but can strip sub-expressions
+ auto &value_expr = expr.get_value_expr ();
+ value_expr->accept_vis (*this);
+ if (value_expr->is_marked_for_strip ())
+ rust_error_at (value_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+
+ // can't strip if block itself, but can strip sub-expressions
+ auto &if_block = expr.get_if_block ();
+ if_block->accept_vis (*this);
+ if (if_block->is_marked_for_strip ())
+ rust_error_at (if_block->get_locus_slow (),
+ "cannot strip block expression in this position - outer "
+ "attributes not allowed");
+
+ // can't strip if expr itself, but can strip sub-expressions
+ auto &conseq_if_expr = expr.get_conseq_if_expr ();
+ conseq_if_expr->accept_vis (*this);
+ if (conseq_if_expr->is_marked_for_strip ())
+ rust_error_at (conseq_if_expr->get_locus_slow (),
+ "cannot strip consequent if expression in this "
+ "position - outer attributes not allowed");
+ }
+ void visit (AST::IfLetExprConseqIfLet &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ for (auto &pattern : expr.get_patterns ())
+ {
+ pattern->accept_vis (*this);
+ if (pattern->is_marked_for_strip ())
+ rust_error_at (pattern->get_locus_slow (),
+ "cannot strip pattern in this position");
+ }
+
+ // can't strip value expr itself, but can strip sub-expressions
+ auto &value_expr = expr.get_value_expr ();
+ value_expr->accept_vis (*this);
+ if (value_expr->is_marked_for_strip ())
+ rust_error_at (value_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+
+ // can't strip if block itself, but can strip sub-expressions
+ auto &if_block = expr.get_if_block ();
+ if_block->accept_vis (*this);
+ if (if_block->is_marked_for_strip ())
+ rust_error_at (if_block->get_locus_slow (),
+ "cannot strip block expression in this position - outer "
+ "attributes not allowed");
+
+ // can't strip if let expr itself, but can strip sub-expressions
+ auto &conseq_if_let_expr = expr.get_conseq_if_let_expr ();
+ conseq_if_let_expr->accept_vis (*this);
+ if (conseq_if_let_expr->is_marked_for_strip ())
+ rust_error_at (conseq_if_let_expr->get_locus_slow (),
+ "cannot strip consequent if let expression in this "
+ "position - outer attributes not "
+ "allowed");
+ }
+ void visit (AST::MatchExpr &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ // inner attr strip test
+ expander.expand_cfg_attrs (expr.get_inner_attrs ());
+ if (expander.fails_cfg (expr.get_inner_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ // can't strip scrutinee expr itself, but can strip sub-expressions
+ auto &scrutinee_expr = expr.get_scrutinee_expr ();
+ scrutinee_expr->accept_vis (*this);
+ if (scrutinee_expr->is_marked_for_strip ())
+ rust_error_at (scrutinee_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+
+ // strip match cases
+ auto &match_cases = expr.get_match_cases ();
+ for (int i = 0; i < match_cases.size ();)
+ {
+ auto &match_case = match_cases[i];
+
+ // strip match case based on outer attributes in match arm
+ auto &match_arm = match_case.get_arm ();
+ expander.expand_cfg_attrs (match_arm.get_outer_attrs ());
+ if (expander.fails_cfg (match_arm.get_outer_attrs ()))
+ {
+ // strip match case
+ match_cases.erase (match_cases.begin () + i);
+ continue;
+ }
+
+ for (auto &pattern : match_arm.get_patterns ())
+ {
+ pattern->accept_vis (*this);
+ if (pattern->is_marked_for_strip ())
+ rust_error_at (pattern->get_locus_slow (),
+ "cannot strip pattern in this position");
+ }
+
+ /* assuming that guard expression cannot be stripped as
+ * strictly speaking you would have to strip the whole guard to
+ * make syntactical sense, which you can't do. as such, only
+ * strip sub-expressions */
+ if (match_arm.has_match_arm_guard ())
+ {
+ auto &guard_expr = match_arm.get_guard_expr ();
+ guard_expr->accept_vis (*this);
+ if (guard_expr->is_marked_for_strip ())
+ rust_error_at (guard_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+
+ // strip sub-expressions from match cases
+ auto &case_expr = match_case.get_expr ();
+ case_expr->accept_vis (*this);
+ if (case_expr->is_marked_for_strip ())
+ rust_error_at (case_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+
+ // increment to next case if haven't continued
+ i++;
+ }
+ }
+ void visit (AST::AwaitExpr &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ /* can't strip awaited expr itself, but can strip sub-expressions
+ * - this is because you can't have no expr to await */
+ auto &awaited_expr = expr.get_awaited_expr ();
+ awaited_expr->accept_vis (*this);
+ if (awaited_expr->is_marked_for_strip ())
+ rust_error_at (awaited_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::AsyncBlockExpr &expr) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (expr.get_outer_attrs ());
+ if (expander.fails_cfg (expr.get_outer_attrs ()))
+ {
+ expr.mark_for_strip ();
+ return;
+ }
+
+ // can't strip block itself, but can strip sub-expressions
+ auto &block_expr = expr.get_block_expr ();
+ block_expr->accept_vis (*this);
+ if (block_expr->is_marked_for_strip ())
+ rust_error_at (block_expr->get_locus_slow (),
+ "cannot strip block expression in this position - outer "
+ "attributes not allowed");
+ }
+
+ void visit (AST::TypeParam &param) override
+ {
+ // outer attributes don't actually do anything, so ignore them
+
+ if (param.has_type_param_bounds ())
+ {
+ // don't strip directly, only components of bounds
+ for (auto &bound : param.get_type_param_bounds ())
+ bound->accept_vis (*this);
+ }
+
+ if (param.has_type ())
+ {
+ auto &type = param.get_type ();
+ type->accept_vis (*this);
+ if (type->is_marked_for_strip ())
+ rust_error_at (type->get_locus_slow (),
+ "cannot strip type in this position");
+ }
+ }
+ void visit (AST::LifetimeWhereClauseItem &) override
+ {
+ // shouldn't require
+ }
+ void visit (AST::TypeBoundWhereClauseItem &item) override
+ {
+ // for lifetimes shouldn't require
+
+ auto &type = item.get_type ();
+ type->accept_vis (*this);
+ if (type->is_marked_for_strip ())
+ rust_error_at (type->get_locus_slow (),
+ "cannot strip type in this position");
+
+ // don't strip directly, only components of bounds
+ for (auto &bound : item.get_type_param_bounds ())
+ bound->accept_vis (*this);
+ }
+ void visit (AST::Method &method) override
+ {
+ // initial test based on outer attrs
+ expander.expand_cfg_attrs (method.get_outer_attrs ());
+ if (expander.fails_cfg (method.get_outer_attrs ()))
+ {
+ method.mark_for_strip ();
+ return;
+ }
+
+ // just expand sub-stuff - can't actually strip generic params themselves
+ for (auto &param : method.get_generic_params ())
+ param->accept_vis (*this);
+
+ /* assuming you can't strip self param - wouldn't be a method
+ * anymore. spec allows outer attrs on self param, but doesn't
+ * specify whether cfg is used. */
+ expand_self_param (method.get_self_param ());
+
+ /* strip method parameters if required - this is specifically
+ * allowed by spec */
+ expand_function_params (method.get_function_params ());
+
+ if (method.has_return_type ())
+ {
+ auto &return_type = method.get_return_type ();
+ return_type->accept_vis (*this);
+ if (return_type->is_marked_for_strip ())
+ rust_error_at (return_type->get_locus_slow (),
+ "cannot strip type in this position");
+ }
+
+ if (method.has_where_clause ())
+ expand_where_clause (method.get_where_clause ());
+
+ /* body should always exist - if error state, should have returned
+ * before now */
+ // can't strip block itself, but can strip sub-expressions
+ auto &block_expr = method.get_definition ();
+ block_expr->accept_vis (*this);
+ if (block_expr->is_marked_for_strip ())
+ rust_error_at (block_expr->get_locus_slow (),
+ "cannot strip block expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::ModuleBodied &module) override
+ {
+ // strip test based on outer attrs
+ expander.expand_cfg_attrs (module.get_outer_attrs ());
+ if (expander.fails_cfg (module.get_outer_attrs ()))
+ {
+ module.mark_for_strip ();
+ return;
+ }
+
+ // strip test based on inner attrs
+ expander.expand_cfg_attrs (module.get_inner_attrs ());
+ if (expander.fails_cfg (module.get_inner_attrs ()))
+ {
+ module.mark_for_strip ();
+ return;
+ }
+
+ // strip items if required
+ auto &items = module.get_items ();
+ for (int i = 0; i < items.size ();)
+ {
+ auto &item = items[i];
+
+ // mark for stripping if required
+ item->accept_vis (*this);
+
+ if (item->is_marked_for_strip ())
+ items.erase (items.begin () + i);
+ else
+ i++;
+ }
+ }
+ void visit (AST::ModuleNoBody &module) override
+ {
+ // strip test based on outer attrs
+ expander.expand_cfg_attrs (module.get_outer_attrs ());
+ if (expander.fails_cfg (module.get_outer_attrs ()))
+ {
+ module.mark_for_strip ();
+ return;
+ }
+ }
+ void visit (AST::ExternCrate &crate) override
+ {
+ // strip test based on outer attrs
+ expander.expand_cfg_attrs (crate.get_outer_attrs ());
+ if (expander.fails_cfg (crate.get_outer_attrs ()))
+ {
+ crate.mark_for_strip ();
+ return;
+ }
+ }
+ void visit (AST::UseTreeGlob &) override
+ {
+ // shouldn't require?
+ }
+ void visit (AST::UseTreeList &) override
+ {
+ // shouldn't require?
+ }
+ void visit (AST::UseTreeRebind &) override
+ {
+ // shouldn't require?
+ }
+ void visit (AST::UseDeclaration &use_decl) override
+ {
+ // strip test based on outer attrs
+ expander.expand_cfg_attrs (use_decl.get_outer_attrs ());
+ if (expander.fails_cfg (use_decl.get_outer_attrs ()))
+ {
+ use_decl.mark_for_strip ();
+ return;
+ }
+ }
+ void visit (AST::Function &function) override
+ {
+ // initial test based on outer attrs
+ expander.expand_cfg_attrs (function.get_outer_attrs ());
+ if (expander.fails_cfg (function.get_outer_attrs ()))
+ {
+ function.mark_for_strip ();
+ return;
+ }
+
+ // just expand sub-stuff - can't actually strip generic params themselves
+ for (auto &param : function.get_generic_params ())
+ param->accept_vis (*this);
+
+ /* strip function parameters if required - this is specifically
+ * allowed by spec */
+ expand_function_params (function.get_function_params ());
+
+ if (function.has_return_type ())
+ {
+ auto &return_type = function.get_return_type ();
+ return_type->accept_vis (*this);
+ if (return_type->is_marked_for_strip ())
+ rust_error_at (return_type->get_locus_slow (),
+ "cannot strip type in this position");
+ }
+
+ if (function.has_where_clause ())
+ expand_where_clause (function.get_where_clause ());
+
+ /* body should always exist - if error state, should have returned
+ * before now */
+ // can't strip block itself, but can strip sub-expressions
+ auto &block_expr = function.get_definition ();
+ block_expr->accept_vis (*this);
+ if (block_expr->is_marked_for_strip ())
+ rust_error_at (block_expr->get_locus_slow (),
+ "cannot strip block expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::TypeAlias &type_alias) override
+ {
+ // initial test based on outer attrs
+ expander.expand_cfg_attrs (type_alias.get_outer_attrs ());
+ if (expander.fails_cfg (type_alias.get_outer_attrs ()))
+ {
+ type_alias.mark_for_strip ();
+ return;
+ }
+
+ // just expand sub-stuff - can't actually strip generic params themselves
+ for (auto &param : type_alias.get_generic_params ())
+ param->accept_vis (*this);
+
+ if (type_alias.has_where_clause ())
+ expand_where_clause (type_alias.get_where_clause ());
+
+ auto &type = type_alias.get_type_aliased ();
+ type->accept_vis (*this);
+ if (type->is_marked_for_strip ())
+ rust_error_at (type->get_locus_slow (),
+ "cannot strip type in this position");
+ }
+ void visit (AST::StructStruct &struct_item) override
+ {
+ // initial test based on outer attrs
+ expander.expand_cfg_attrs (struct_item.get_outer_attrs ());
+ if (expander.fails_cfg (struct_item.get_outer_attrs ()))
+ {
+ struct_item.mark_for_strip ();
+ return;
+ }
+
+ // just expand sub-stuff - can't actually strip generic params themselves
+ for (auto &param : struct_item.get_generic_params ())
+ param->accept_vis (*this);
+
+ if (struct_item.has_where_clause ())
+ expand_where_clause (struct_item.get_where_clause ());
+
+ /* strip struct fields if required - this is presumably
+ * allowed by spec */
+ expand_struct_fields (struct_item.get_fields ());
+ }
+ void visit (AST::TupleStruct &tuple_struct) override
+ {
+ // initial test based on outer attrs
+ expander.expand_cfg_attrs (tuple_struct.get_outer_attrs ());
+ if (expander.fails_cfg (tuple_struct.get_outer_attrs ()))
+ {
+ tuple_struct.mark_for_strip ();
+ return;
+ }
+
+ // just expand sub-stuff - can't actually strip generic params themselves
+ for (auto &param : tuple_struct.get_generic_params ())
+ param->accept_vis (*this);
+
+ /* strip struct fields if required - this is presumably
+ * allowed by spec */
+ expand_tuple_fields (tuple_struct.get_fields ());
+
+ if (tuple_struct.has_where_clause ())
+ expand_where_clause (tuple_struct.get_where_clause ());
+ }
+ void visit (AST::EnumItem &item) override
+ {
+ // initial test based on outer attrs
+ expander.expand_cfg_attrs (item.get_outer_attrs ());
+ if (expander.fails_cfg (item.get_outer_attrs ()))
+ {
+ item.mark_for_strip ();
+ return;
+ }
+ }
+ void visit (AST::EnumItemTuple &item) override
+ {
+ // initial test based on outer attrs
+ expander.expand_cfg_attrs (item.get_outer_attrs ());
+ if (expander.fails_cfg (item.get_outer_attrs ()))
+ {
+ item.mark_for_strip ();
+ return;
+ }
+
+ /* strip item fields if required - this is presumably
+ * allowed by spec */
+ expand_tuple_fields (item.get_tuple_fields ());
+ }
+ void visit (AST::EnumItemStruct &item) override
+ {
+ // initial test based on outer attrs
+ expander.expand_cfg_attrs (item.get_outer_attrs ());
+ if (expander.fails_cfg (item.get_outer_attrs ()))
+ {
+ item.mark_for_strip ();
+ return;
+ }
+
+ /* strip item fields if required - this is presumably
+ * allowed by spec */
+ expand_struct_fields (item.get_struct_fields ());
+ }
+ void visit (AST::EnumItemDiscriminant &item) override
+ {
+ // initial test based on outer attrs
+ expander.expand_cfg_attrs (item.get_outer_attrs ());
+ if (expander.fails_cfg (item.get_outer_attrs ()))
+ {
+ item.mark_for_strip ();
+ return;
+ }
+
+ /* strip any internal sub-expressions - expression itself isn't
+ * allowed to have external attributes in this position so can't be
+ * stripped. */
+ auto &expr = item.get_expr ();
+ expr->accept_vis (*this);
+ if (expr->is_marked_for_strip ())
+ rust_error_at (expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::Enum &enum_item) override
+ {
+ // initial test based on outer attrs
+ expander.expand_cfg_attrs (enum_item.get_outer_attrs ());
+ if (expander.fails_cfg (enum_item.get_outer_attrs ()))
+ {
+ enum_item.mark_for_strip ();
+ return;
+ }
+
+ // just expand sub-stuff - can't actually strip generic params themselves
+ for (auto &param : enum_item.get_generic_params ())
+ param->accept_vis (*this);
+
+ if (enum_item.has_where_clause ())
+ expand_where_clause (enum_item.get_where_clause ());
+
+ /* strip enum fields if required - this is presumably
+ * allowed by spec */
+ auto &variants = enum_item.get_variants ();
+ for (int i = 0; i < variants.size ();)
+ {
+ auto &variant = variants[i];
+
+ // mark for stripping if required
+ variant->accept_vis (*this);
+
+ if (variant->is_marked_for_strip ())
+ variants.erase (variants.begin () + i);
+ else
+ i++;
+ }
+ }
+ void visit (AST::Union &union_item) override
+ {
+ // initial test based on outer attrs
+ expander.expand_cfg_attrs (union_item.get_outer_attrs ());
+ if (expander.fails_cfg (union_item.get_outer_attrs ()))
+ {
+ union_item.mark_for_strip ();
+ return;
+ }
+
+ // just expand sub-stuff - can't actually strip generic params themselves
+ for (auto &param : union_item.get_generic_params ())
+ param->accept_vis (*this);
+
+ if (union_item.has_where_clause ())
+ expand_where_clause (union_item.get_where_clause ());
+
+ /* strip union fields if required - this is presumably
+ * allowed by spec */
+ expand_struct_fields (union_item.get_variants ());
+ }
+ void visit (AST::ConstantItem &const_item) override
+ {
+ // initial test based on outer attrs
+ expander.expand_cfg_attrs (const_item.get_outer_attrs ());
+ if (expander.fails_cfg (const_item.get_outer_attrs ()))
+ {
+ const_item.mark_for_strip ();
+ return;
+ }
+
+ // strip any sub-types
+ auto &type = const_item.get_type ();
+ type->accept_vis (*this);
+ if (type->is_marked_for_strip ())
+ rust_error_at (type->get_locus_slow (),
+ "cannot strip type in this position");
+
+ /* strip any internal sub-expressions - expression itself isn't
+ * allowed to have external attributes in this position so can't be
+ * stripped. */
+ auto &expr = const_item.get_expr ();
+ expr->accept_vis (*this);
+ if (expr->is_marked_for_strip ())
+ rust_error_at (expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::StaticItem &static_item) override
+ {
+ // initial test based on outer attrs
+ expander.expand_cfg_attrs (static_item.get_outer_attrs ());
+ if (expander.fails_cfg (static_item.get_outer_attrs ()))
+ {
+ static_item.mark_for_strip ();
+ return;
+ }
+
+ // strip any sub-types
+ auto &type = static_item.get_type ();
+ type->accept_vis (*this);
+ if (type->is_marked_for_strip ())
+ rust_error_at (type->get_locus_slow (),
+ "cannot strip type in this position");
+
+ /* strip any internal sub-expressions - expression itself isn't
+ * allowed to have external attributes in this position so can't be
+ * stripped. */
+ auto &expr = static_item.get_expr ();
+ expr->accept_vis (*this);
+ if (expr->is_marked_for_strip ())
+ rust_error_at (expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ void visit (AST::TraitItemFunc &item) override
+ {
+ // initial test based on outer attrs
+ expander.expand_cfg_attrs (item.get_outer_attrs ());
+ if (expander.fails_cfg (item.get_outer_attrs ()))
+ {
+ item.mark_for_strip ();
+ return;
+ }
+
+ expand_trait_function_decl (item.get_trait_function_decl ());
+
+ if (item.has_definition ())
+ {
+ /* strip any internal sub-expressions - expression itself isn't
+ * allowed to have external attributes in this position so can't be
+ * stripped. */
+ auto &block = item.get_definition ();
+ block->accept_vis (*this);
+ if (block->is_marked_for_strip ())
+ rust_error_at (block->get_locus_slow (),
+ "cannot strip block expression in this "
+ "position - outer attributes not allowed");
+ }
+ }
+ void visit (AST::TraitItemMethod &item) override
+ {
+ // initial test based on outer attrs
+ expander.expand_cfg_attrs (item.get_outer_attrs ());
+ if (expander.fails_cfg (item.get_outer_attrs ()))
+ {
+ item.mark_for_strip ();
+ return;
+ }
+
+ expand_trait_method_decl (item.get_trait_method_decl ());
+
+ if (item.has_definition ())
+ {
+ /* strip any internal sub-expressions - expression itself isn't
+ * allowed to have external attributes in this position so can't be
+ * stripped. */
+ auto &block = item.get_definition ();
+ block->accept_vis (*this);
+ if (block->is_marked_for_strip ())
+ rust_error_at (block->get_locus_slow (),
+ "cannot strip block expression in this "
+ "position - outer attributes not allowed");
+ }
+ }
+ void visit (AST::TraitItemConst &item) override
+ {
+ // initial test based on outer attrs
+ expander.expand_cfg_attrs (item.get_outer_attrs ());
+ if (expander.fails_cfg (item.get_outer_attrs ()))
+ {
+ item.mark_for_strip ();
+ return;
+ }
+
+ // strip any sub-types
+ auto &type = item.get_type ();
+ type->accept_vis (*this);
+ if (type->is_marked_for_strip ())
+ rust_error_at (type->get_locus_slow (),
+ "cannot strip type in this position");
+
+ /* strip any internal sub-expressions - expression itself isn't
+ * allowed to have external attributes in this position so can't be
+ * stripped */
+ if (item.has_expression ())
+ {
+ auto &expr = item.get_expr ();
+ expr->accept_vis (*this);
+ if (expr->is_marked_for_strip ())
+ rust_error_at (expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ }
+ void visit (AST::TraitItemType &item) override
+ {
+ // initial test based on outer attrs
+ expander.expand_cfg_attrs (item.get_outer_attrs ());
+ if (expander.fails_cfg (item.get_outer_attrs ()))
+ {
+ item.mark_for_strip ();
+ return;
+ }
+
+ if (item.has_type_param_bounds ())
+ {
+ // don't strip directly, only components of bounds
+ for (auto &bound : item.get_type_param_bounds ())
+ bound->accept_vis (*this);
+ }
+ }
+ void visit (AST::Trait &trait) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (trait.get_outer_attrs ());
+ if (expander.fails_cfg (trait.get_outer_attrs ()))
+ {
+ trait.mark_for_strip ();
+ return;
+ }
+
+ // strip test based on inner attrs
+ expander.expand_cfg_attrs (trait.get_inner_attrs ());
+ if (expander.fails_cfg (trait.get_inner_attrs ()))
+ {
+ trait.mark_for_strip ();
+ return;
+ }
+
+ // just expand sub-stuff - can't actually strip generic params themselves
+ for (auto &param : trait.get_generic_params ())
+ param->accept_vis (*this);
+
+ if (trait.has_type_param_bounds ())
+ {
+ // don't strip directly, only components of bounds
+ for (auto &bound : trait.get_type_param_bounds ())
+ bound->accept_vis (*this);
+ }
+
+ if (trait.has_where_clause ())
+ expand_where_clause (trait.get_where_clause ());
+
+ // strip trait items if required
+ auto &trait_items = trait.get_trait_items ();
+ for (int i = 0; i < trait_items.size ();)
+ {
+ auto &item = trait_items[i];
+
+ // mark for stripping if required
+ item->accept_vis (*this);
+
+ if (item->is_marked_for_strip ())
+ trait_items.erase (trait_items.begin () + i);
+ else
+ i++;
+ }
+ }
+ void visit (AST::InherentImpl &impl) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (impl.get_outer_attrs ());
+ if (expander.fails_cfg (impl.get_outer_attrs ()))
+ {
+ impl.mark_for_strip ();
+ return;
+ }
+
+ // strip test based on inner attrs
+ expander.expand_cfg_attrs (impl.get_inner_attrs ());
+ if (expander.fails_cfg (impl.get_inner_attrs ()))
+ {
+ impl.mark_for_strip ();
+ return;
+ }
+
+ // just expand sub-stuff - can't actually strip generic params themselves
+ for (auto &param : impl.get_generic_params ())
+ param->accept_vis (*this);
+
+ auto &type = impl.get_type ();
+ type->accept_vis (*this);
+ if (type->is_marked_for_strip ())
+ rust_error_at (type->get_locus_slow (),
+ "cannot strip type in this position");
+
+ if (impl.has_where_clause ())
+ expand_where_clause (impl.get_where_clause ());
+
+ // strip inherent impl items if required
+ auto &impl_items = impl.get_impl_items ();
+ for (int i = 0; i < impl_items.size ();)
+ {
+ auto &item = impl_items[i];
+
+ // mark for stripping if required
+ item->accept_vis (*this);
+
+ if (item->is_marked_for_strip ())
+ impl_items.erase (impl_items.begin () + i);
+ else
+ i++;
+ }
+ }
+ void visit (AST::TraitImpl &impl) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (impl.get_outer_attrs ());
+ if (expander.fails_cfg (impl.get_outer_attrs ()))
+ {
+ impl.mark_for_strip ();
+ return;
+ }
+
+ // strip test based on inner attrs
+ expander.expand_cfg_attrs (impl.get_inner_attrs ());
+ if (expander.fails_cfg (impl.get_inner_attrs ()))
+ {
+ impl.mark_for_strip ();
+ return;
+ }
+
+ // just expand sub-stuff - can't actually strip generic params themselves
+ for (auto &param : impl.get_generic_params ())
+ param->accept_vis (*this);
+
+ auto &type = impl.get_type ();
+ type->accept_vis (*this);
+ if (type->is_marked_for_strip ())
+ rust_error_at (type->get_locus_slow (),
+ "cannot strip type in this position");
+
+ auto &trait_path = impl.get_trait_path ();
+ visit (trait_path);
+ if (trait_path.is_marked_for_strip ())
+ rust_error_at (trait_path.get_locus (),
+ "cannot strip typepath in this position");
+
+ if (impl.has_where_clause ())
+ expand_where_clause (impl.get_where_clause ());
+
+ // strip trait impl items if required
+ auto &impl_items = impl.get_impl_items ();
+ for (int i = 0; i < impl_items.size ();)
+ {
+ auto &item = impl_items[i];
+
+ // mark for stripping if required
+ item->accept_vis (*this);
+
+ if (item->is_marked_for_strip ())
+ impl_items.erase (impl_items.begin () + i);
+ else
+ i++;
+ }
+ }
+ void visit (AST::ExternalStaticItem &item) override
+ {
+ // strip test based on outer attrs
+ expander.expand_cfg_attrs (item.get_outer_attrs ());
+ if (expander.fails_cfg (item.get_outer_attrs ()))
+ {
+ item.mark_for_strip ();
+ return;
+ }
+
+ auto &type = item.get_type ();
+ type->accept_vis (*this);
+ if (type->is_marked_for_strip ())
+ rust_error_at (type->get_locus_slow (),
+ "cannot strip type in this position");
+ }
+ void visit (AST::ExternalFunctionItem &item) override
+ {
+ // strip test based on outer attrs
+ expander.expand_cfg_attrs (item.get_outer_attrs ());
+ if (expander.fails_cfg (item.get_outer_attrs ()))
+ {
+ item.mark_for_strip ();
+ return;
+ }
+
+ // just expand sub-stuff - can't actually strip generic params themselves
+ for (auto &param : item.get_generic_params ())
+ param->accept_vis (*this);
+
+ /* strip function parameters if required - this is specifically
+ * allowed by spec */
+ auto &params = item.get_function_params ();
+ for (int i = 0; i < params.size ();)
+ {
+ auto &param = params[i];
+
+ auto &param_attrs = param.get_outer_attrs ();
+ expander.expand_cfg_attrs (param_attrs);
+ if (expander.fails_cfg (param_attrs))
+ {
+ params.erase (params.begin () + i);
+ continue;
+ }
+
+ auto &type = param.get_type ();
+ type->accept_vis (*this);
+ if (type->is_marked_for_strip ())
+ rust_error_at (type->get_locus_slow (),
+ "cannot strip type in this position");
+
+ // increment if nothing else happens
+ i++;
+ }
+ /* NOTE: these are extern function params, which may have different
+ * rules and restrictions to "normal" function params. So expansion
+ * handled separately. */
+
+ /* TODO: assuming that variadic nature cannot be stripped. If this
+ * is not true, then have code here to do so. */
+
+ if (item.has_return_type ())
+ {
+ auto &return_type = item.get_return_type ();
+ return_type->accept_vis (*this);
+ if (return_type->is_marked_for_strip ())
+ rust_error_at (return_type->get_locus_slow (),
+ "cannot strip type in this position");
+ }
+
+ if (item.has_where_clause ())
+ expand_where_clause (item.get_where_clause ());
+ }
+ void visit (AST::ExternBlock &block) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (block.get_outer_attrs ());
+ if (expander.fails_cfg (block.get_outer_attrs ()))
+ {
+ block.mark_for_strip ();
+ return;
+ }
+
+ // strip test based on inner attrs
+ expander.expand_cfg_attrs (block.get_inner_attrs ());
+ if (expander.fails_cfg (block.get_inner_attrs ()))
+ {
+ block.mark_for_strip ();
+ return;
+ }
+
+ // strip external items if required
+ auto &extern_items = block.get_extern_items ();
+ for (int i = 0; i < extern_items.size ();)
+ {
+ auto &item = extern_items[i];
+
+ // mark for stripping if required
+ item->accept_vis (*this);
+
+ if (item->is_marked_for_strip ())
+ extern_items.erase (extern_items.begin () + i);
+ else
+ i++;
+ }
+ }
+
+ // I don't think it would be possible to strip macros without expansion
+ void visit (AST::MacroMatchFragment &) override {}
+ void visit (AST::MacroMatchRepetition &) override {}
+ void visit (AST::MacroMatcher &) override {}
+ void visit (AST::MacroRulesDefinition &rules_def) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (rules_def.get_outer_attrs ());
+ if (expander.fails_cfg (rules_def.get_outer_attrs ()))
+ {
+ rules_def.mark_for_strip ();
+ return;
+ }
+
+ // I don't think any macro rules can be stripped in any way
+ }
+ void visit (AST::MacroInvocation &macro_invoc) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (macro_invoc.get_outer_attrs ());
+ if (expander.fails_cfg (macro_invoc.get_outer_attrs ()))
+ {
+ macro_invoc.mark_for_strip ();
+ return;
+ }
+
+ // I don't think any macro token trees can be stripped in any way
+
+ // TODO: maybe have stripping behaviour for the cfg! macro here?
+ }
+ void visit (AST::MetaItemPath &) override {}
+ void visit (AST::MetaItemSeq &) override {}
+ void visit (AST::MetaWord &) override {}
+ void visit (AST::MetaNameValueStr &) override {}
+ void visit (AST::MetaListPaths &) override {}
+ void visit (AST::MetaListNameValueStr &) override {}
+
+ void visit (AST::LiteralPattern &) override
+ {
+ // not possible
+ }
+ void visit (AST::IdentifierPattern &pattern) override
+ {
+ // can only strip sub-patterns of the inner pattern to bind
+ if (!pattern.has_pattern_to_bind ())
+ return;
+
+ auto &sub_pattern = pattern.get_pattern_to_bind ();
+ sub_pattern->accept_vis (*this);
+ if (sub_pattern->is_marked_for_strip ())
+ rust_error_at (sub_pattern->get_locus_slow (),
+ "cannot strip pattern in this position");
+ }
+ void visit (AST::WildcardPattern &) override
+ {
+ // not possible
+ }
+ void visit (AST::RangePatternBoundLiteral &) override
+ {
+ // not possible
+ }
+ void visit (AST::RangePatternBoundPath &bound) override
+ {
+ // can expand path, but not strip it directly
+ auto &path = bound.get_path ();
+ visit (path);
+ if (path.is_marked_for_strip ())
+ rust_error_at (path.get_locus (), "cannot strip path in this position");
+ }
+ void visit (AST::RangePatternBoundQualPath &bound) override
+ {
+ // can expand path, but not strip it directly
+ auto &path = bound.get_qualified_path ();
+ visit (path);
+ if (path.is_marked_for_strip ())
+ rust_error_at (path.get_locus (), "cannot strip path in this position");
+ }
+ void visit (AST::RangePattern &pattern) override
+ {
+ // should have no capability to strip lower or upper bounds, only expand
+ pattern.get_lower_bound ()->accept_vis (*this);
+ pattern.get_upper_bound ()->accept_vis (*this);
+ }
+ void visit (AST::ReferencePattern &pattern) override
+ {
+ auto &sub_pattern = pattern.get_referenced_pattern ();
+ sub_pattern->accept_vis (*this);
+ if (sub_pattern->is_marked_for_strip ())
+ rust_error_at (sub_pattern->get_locus_slow (),
+ "cannot strip pattern in this position");
+ }
+ void visit (AST::StructPatternFieldTuplePat &field) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (field.get_outer_attrs ());
+ if (expander.fails_cfg (field.get_outer_attrs ()))
+ {
+ field.mark_for_strip ();
+ return;
+ }
+
+ // strip sub-patterns (can't strip top-level pattern)
+ auto &sub_pattern = field.get_index_pattern ();
+ sub_pattern->accept_vis (*this);
+ if (sub_pattern->is_marked_for_strip ())
+ rust_error_at (sub_pattern->get_locus_slow (),
+ "cannot strip pattern in this position");
+ }
+ void visit (AST::StructPatternFieldIdentPat &field) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (field.get_outer_attrs ());
+ if (expander.fails_cfg (field.get_outer_attrs ()))
+ {
+ field.mark_for_strip ();
+ return;
+ }
+
+ // strip sub-patterns (can't strip top-level pattern)
+ auto &sub_pattern = field.get_ident_pattern ();
+ sub_pattern->accept_vis (*this);
+ if (sub_pattern->is_marked_for_strip ())
+ rust_error_at (sub_pattern->get_locus_slow (),
+ "cannot strip pattern in this position");
+ }
+ void visit (AST::StructPatternFieldIdent &field) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (field.get_outer_attrs ());
+ if (expander.fails_cfg (field.get_outer_attrs ()))
+ {
+ field.mark_for_strip ();
+ return;
+ }
+ }
+ void visit (AST::StructPattern &pattern) override
+ {
+ // expand (but don't strip) path
+ auto &path = pattern.get_path ();
+ visit (path);
+ if (path.is_marked_for_strip ())
+ rust_error_at (path.get_locus (), "cannot strip path in this position");
+
+ // TODO: apparently struct pattern fields can have outer attrs. so can they
+ // be stripped?
+ if (!pattern.has_struct_pattern_elems ())
+ return;
+
+ auto &elems = pattern.get_struct_pattern_elems ();
+
+ // assuming you can strip struct pattern fields
+ auto &fields = elems.get_struct_pattern_fields ();
+ for (int i = 0; i < fields.size ();)
+ {
+ auto &field = fields[i];
+
+ field->accept_vis (*this);
+
+ if (field->is_marked_for_strip ())
+ fields.erase (fields.begin () + i);
+ else
+ i++;
+ }
+
+ // assuming you can strip the ".." part
+ if (elems.has_etc ())
+ {
+ expander.expand_cfg_attrs (elems.get_etc_outer_attrs ());
+ if (expander.fails_cfg (elems.get_etc_outer_attrs ()))
+ elems.strip_etc ();
+ }
+ }
+ void visit (AST::TupleStructItemsNoRange &tuple_items) override
+ {
+ // can't strip individual patterns, only sub-patterns
+ for (auto &pattern : tuple_items.get_patterns ())
+ {
+ pattern->accept_vis (*this);
+
+ if (pattern->is_marked_for_strip ())
+ rust_error_at (pattern->get_locus_slow (),
+ "cannot strip pattern in this position");
+ // TODO: quit stripping now? or keep going?
+ }
+ }
+ void visit (AST::TupleStructItemsRange &tuple_items) override
+ {
+ // can't strip individual patterns, only sub-patterns
+ for (auto &lower_pattern : tuple_items.get_lower_patterns ())
+ {
+ lower_pattern->accept_vis (*this);
+
+ if (lower_pattern->is_marked_for_strip ())
+ rust_error_at (lower_pattern->get_locus_slow (),
+ "cannot strip pattern in this position");
+ // TODO: quit stripping now? or keep going?
+ }
+ for (auto &upper_pattern : tuple_items.get_upper_patterns ())
+ {
+ upper_pattern->accept_vis (*this);
+
+ if (upper_pattern->is_marked_for_strip ())
+ rust_error_at (upper_pattern->get_locus_slow (),
+ "cannot strip pattern in this position");
+ // TODO: quit stripping now? or keep going?
+ }
+ }
+ void visit (AST::TupleStructPattern &pattern) override
+ {
+ // expand (but don't strip) path
+ auto &path = pattern.get_path ();
+ visit (path);
+ if (path.is_marked_for_strip ())
+ rust_error_at (path.get_locus (), "cannot strip path in this position");
+
+ if (pattern.has_items ())
+ pattern.get_items ()->accept_vis (*this);
+ }
+ void visit (AST::TuplePatternItemsMultiple &tuple_items) override
+ {
+ // can't strip individual patterns, only sub-patterns
+ for (auto &pattern : tuple_items.get_patterns ())
+ {
+ pattern->accept_vis (*this);
+
+ if (pattern->is_marked_for_strip ())
+ rust_error_at (pattern->get_locus_slow (),
+ "cannot strip pattern in this position");
+ // TODO: quit stripping now? or keep going?
+ }
+ }
+ void visit (AST::TuplePatternItemsRanged &tuple_items) override
+ {
+ // can't strip individual patterns, only sub-patterns
+ for (auto &lower_pattern : tuple_items.get_lower_patterns ())
+ {
+ lower_pattern->accept_vis (*this);
+
+ if (lower_pattern->is_marked_for_strip ())
+ rust_error_at (lower_pattern->get_locus_slow (),
+ "cannot strip pattern in this position");
+ // TODO: quit stripping now? or keep going?
+ }
+ for (auto &upper_pattern : tuple_items.get_upper_patterns ())
+ {
+ upper_pattern->accept_vis (*this);
+
+ if (upper_pattern->is_marked_for_strip ())
+ rust_error_at (upper_pattern->get_locus_slow (),
+ "cannot strip pattern in this position");
+ // TODO: quit stripping now? or keep going?
+ }
+ }
+ void visit (AST::TuplePattern &pattern) override
+ {
+ if (pattern.has_tuple_pattern_items ())
+ pattern.get_items ()->accept_vis (*this);
+ }
+ void visit (AST::GroupedPattern &pattern) override
+ {
+ // can't strip inner pattern, only sub-patterns
+ auto &pattern_in_parens = pattern.get_pattern_in_parens ();
+
+ pattern_in_parens->accept_vis (*this);
+
+ if (pattern_in_parens->is_marked_for_strip ())
+ rust_error_at (pattern_in_parens->get_locus_slow (),
+ "cannot strip pattern in this position");
+ }
+ void visit (AST::SlicePattern &pattern) override
+ {
+ // can't strip individual patterns, only sub-patterns
+ for (auto &item : pattern.get_items ())
+ {
+ item->accept_vis (*this);
+
+ if (item->is_marked_for_strip ())
+ rust_error_at (item->get_locus_slow (),
+ "cannot strip pattern in this position");
+ // TODO: quit stripping now? or keep going?
+ }
+ }
+
+ void visit (AST::EmptyStmt &) override
+ {
+ // assuming no outer attributes, so nothing can happen
+ }
+ void visit (AST::LetStmt &stmt) override
+ {
+ // initial strip test based on outer attrs
+ expander.expand_cfg_attrs (stmt.get_outer_attrs ());
+ if (expander.fails_cfg (stmt.get_outer_attrs ()))
+ {
+ stmt.mark_for_strip ();
+ return;
+ }
+
+ // can't strip pattern, but call for sub-patterns
+ auto &pattern = stmt.get_pattern ();
+ pattern->accept_vis (*this);
+ if (pattern->is_marked_for_strip ())
+ rust_error_at (pattern->get_locus_slow (),
+ "cannot strip pattern in this position");
+
+ // similar for type
+ if (stmt.has_type ())
+ {
+ auto &type = stmt.get_type ();
+ type->accept_vis (*this);
+ if (type->is_marked_for_strip ())
+ rust_error_at (type->get_locus_slow (),
+ "cannot strip type in this position");
+ }
+
+ /* strip any internal sub-expressions - expression itself isn't
+ * allowed to have external attributes in this position so can't be
+ * stripped */
+ if (stmt.has_init_expr ())
+ {
+ auto &init_expr = stmt.get_init_expr ();
+ init_expr->accept_vis (*this);
+ if (init_expr->is_marked_for_strip ())
+ rust_error_at (init_expr->get_locus_slow (),
+ "cannot strip expression in this position - outer "
+ "attributes not allowed");
+ }
+ }
+ void visit (AST::ExprStmtWithoutBlock &stmt) override
+ {
+ // outer attributes associated with expr, so rely on expr
+
+ // guard - should prevent null pointer expr
+ if (stmt.is_marked_for_strip ())
+ return;
+
+ // strip if expr is to be stripped
+ auto &expr = stmt.get_expr ();
+ expr->accept_vis (*this);
+ if (expr->is_marked_for_strip ())
+ {
+ stmt.mark_for_strip ();
+ return;
+ }
+ }
+ void visit (AST::ExprStmtWithBlock &stmt) override
+ {
+ // outer attributes associated with expr, so rely on expr
+
+ // guard - should prevent null pointer expr
+ if (stmt.is_marked_for_strip ())
+ return;
+
+ // strip if expr is to be stripped
+ auto &expr = stmt.get_expr ();
+ expr->accept_vis (*this);
+ if (expr->is_marked_for_strip ())
+ {
+ stmt.mark_for_strip ();
+ return;
+ }
+ }
+
+ void visit (AST::TraitBound &bound) override
+ {
+ // nothing in for lifetimes to strip
+
+ // expand but don't strip type path
+ auto &path = bound.get_type_path ();
+ visit (path);
+ if (path.is_marked_for_strip ())
+ rust_error_at (path.get_locus (),
+ "cannot strip type path in this position");
+ }
+ void visit (AST::ImplTraitType &type) override
+ {
+ // don't strip directly, only components of bounds
+ for (auto &bound : type.get_type_param_bounds ())
+ bound->accept_vis (*this);
+ }
+ void visit (AST::TraitObjectType &type) override
+ {
+ // don't strip directly, only components of bounds
+ for (auto &bound : type.get_type_param_bounds ())
+ bound->accept_vis (*this);
+ }
+ void visit (AST::ParenthesisedType &type) override
+ {
+ // expand but don't strip inner type
+ auto &inner_type = type.get_type_in_parens ();
+ inner_type->accept_vis (*this);
+ if (inner_type->is_marked_for_strip ())
+ rust_error_at (inner_type->get_locus_slow (),
+ "cannot strip type in this position");
+ }
+ void visit (AST::ImplTraitTypeOneBound &type) override
+ {
+ // no stripping possible
+ visit (type.get_trait_bound ());
+ }
+ void visit (AST::TraitObjectTypeOneBound &type) override
+ {
+ // no stripping possible
+ visit (type.get_trait_bound ());
+ }
+ void visit (AST::TupleType &type) override
+ {
+ // TODO: assuming that types can't be stripped as types don't have outer
+ // attributes
+ for (auto &elem_type : type.get_elems ())
+ {
+ elem_type->accept_vis (*this);
+ if (elem_type->is_marked_for_strip ())
+ rust_error_at (elem_type->get_locus_slow (),
+ "cannot strip type in this position");
+ }
+ }
+ void visit (AST::NeverType &) override
+ {
+ // no stripping possible
+ }
+ void visit (AST::RawPointerType &type) override
+ {
+ // expand but don't strip type pointed to
+ auto &pointed_type = type.get_type_pointed_to ();
+ pointed_type->accept_vis (*this);
+ if (pointed_type->is_marked_for_strip ())
+ rust_error_at (pointed_type->get_locus_slow (),
+ "cannot strip type in this position");
+ }
+ void visit (AST::ReferenceType &type) override
+ {
+ // expand but don't strip type referenced
+ auto &referenced_type = type.get_type_referenced ();
+ referenced_type->accept_vis (*this);
+ if (referenced_type->is_marked_for_strip ())
+ rust_error_at (referenced_type->get_locus_slow (),
+ "cannot strip type in this position");
+ }
+ void visit (AST::ArrayType &type) override
+ {
+ // expand but don't strip type referenced
+ auto &base_type = type.get_elem_type ();
+ base_type->accept_vis (*this);
+ if (base_type->is_marked_for_strip ())
+ rust_error_at (base_type->get_locus_slow (),
+ "cannot strip type in this position");
+
+ // same for expression
+ auto &size_expr = type.get_size_expr ();
+ size_expr->accept_vis (*this);
+ if (size_expr->is_marked_for_strip ())
+ rust_error_at (size_expr->get_locus_slow (),
+ "cannot strip expression in this position");
+ }
+ void visit (AST::SliceType &type) override
+ {
+ // expand but don't strip elem type
+ auto &elem_type = type.get_elem_type ();
+ elem_type->accept_vis (*this);
+ if (elem_type->is_marked_for_strip ())
+ rust_error_at (elem_type->get_locus_slow (),
+ "cannot strip type in this position");
+ }
+ void visit (AST::InferredType &) override
+ {
+ // none possible
+ }
+ void visit (AST::BareFunctionType &type) override
+ {
+ // seem to be no generics
+
+ // presumably function params can be stripped
+ auto &params = type.get_function_params ();
+ for (int i = 0; i < params.size ();)
+ {
+ auto &param = params[i];
+
+ auto &param_attrs = param.get_outer_attrs ();
+ expander.expand_cfg_attrs (param_attrs);
+ if (expander.fails_cfg (param_attrs))
+ {
+ params.erase (params.begin () + i);
+ continue;
+ }
+
+ auto &type = param.get_type ();
+ type->accept_vis (*this);
+ if (type->is_marked_for_strip ())
+ rust_error_at (type->get_locus_slow (),
+ "cannot strip type in this position");
+
+ // increment if nothing else happens
+ i++;
+ }
+
+ /* TODO: assuming that variadic nature cannot be stripped. If this
+ * is not true, then have code here to do so. */
+
+ if (type.has_return_type ())
+ {
+ auto &return_type = type.get_return_type ();
+ return_type->accept_vis (*this);
+ if (return_type->is_marked_for_strip ())
+ rust_error_at (return_type->get_locus_slow (),
+ "cannot strip type in this position");
+ }
+
+ // no where clause, apparently
+ }
+};
+
+void
+MacroExpander::expand_invoc (std::unique_ptr<AST::MacroInvocation> &invoc)
+{
+ /* if current expansion depth > recursion limit, create an error (maybe fatal
+ * error) and return */
+
+ /* switch on type of macro:
+ - '!' syntax macro (inner switch)
+ - procedural macro - "A token-based function-like macro"
+ - 'macro_rules' (by example/pattern-match) macro? or not? "an
+ AST-based function-like macro"
+ - else is unreachable
+ - attribute syntax macro (inner switch)
+ - procedural macro attribute syntax - "A token-based attribute macro"
+ - legacy macro attribute syntax? - "an AST-based attribute macro"
+ - non-macro attribute: mark known
+ - else is unreachable
+ - derive macro (inner switch)
+ - derive or legacy derive - "token-based" vs "AST-based"
+ - else is unreachable
+ - derive container macro - unreachable*/
+
+#if 0
+ // macro_rules macro test code
+ auto rule_def = find_rules_def(invoc->get_path());
+ if (rule_def != nullptr) {
+ ASTFrag expanded = expand_decl_macro(invoc, rule_def);
+ /* could make this a data structure containing vectors of exprs, patterns and types (for regular),
+ * and then stmts and items (for semi). Except what about having an expr, then a type? Hmm. Might
+ * have to do the "unified base type" thing OR just have a simulated union, and then have AST frag
+ * be a vector of these simulated unions. */
+
+ // how would errors be signalled? null fragment? something else?
+ // what about error vs just not having stuff in rules definition yet?
+
+ /* replace macro invocation with ast frag. actually, don't have any context here. maybe attach ast
+ * frag to macro invocation, and then have a method above get it? Or just return the ast frag from
+ * this method. */
+ }
+#endif
+}
+
+/* Determines whether any cfg predicate is false and hence item with attributes
+ * should be stripped. */
+bool
+MacroExpander::fails_cfg (std::vector<AST::Attribute> &attrs)
+{
+ for (auto &attr : attrs)
+ {
+ if (attr.get_path () == "cfg" && !attr.check_cfg_predicate (session))
+ return true;
}
+ return false;
+}
+
+// Expands cfg_attr attributes.
+void
+MacroExpander::expand_cfg_attrs (std::vector<AST::Attribute> &attrs)
+{
+ for (int i = 0; i < attrs.size ();)
+ {
+ auto &attr = attrs[i];
+ if (attr.get_path () == "cfg_attr")
+ {
+ if (attr.check_cfg_predicate (session))
+ {
+ // split off cfg_attr
+ std::vector<AST::Attribute> new_attrs
+ = attr.separate_cfg_attrs ();
+
+ // remove attr from vector
+ attrs.erase (attrs.begin () + i);
+
+ // add new attrs to vector
+ attrs.insert (attrs.begin () + i,
+ std::make_move_iterator (new_attrs.begin ()),
+ std::make_move_iterator (new_attrs.end ()));
+ }
- /* Determines whether cfg predicate is true and item with attribute should not
- * be stripped. */
- bool check_cfg_predicate() {}
-
- /* Determines whether cfg predicate is true and item with attribute should not
- * be stripped. */
- bool check_cfg(AST::Attribute& attr) {}
-
- // Expands cfg_attr attributes.
- void expand_attrs_cfgattr(std::vector<AST::Attribute>& attrs) {
- for (auto it = attrs.begin(); it != attrs.end();) {
- auto& attr = *it;
- if (attr.get_path() == "cfg_attr") {
- if (check_cfg(attr)) {
- }
-
- /* do something - if feature (first token in tree) is in fact enabled,
- * make tokens listed afterwards into attributes. i.e.: for
- * [cfg_attr(feature = "wow", wow1, wow2)], if "wow" is true, then add
- * attributes [wow1] and [wow2] to attribute list. This can also be
- * recursive, so check for expanded attributes being recursive and
- * possibly recursively call the expand_attrs? */
- } else {
- ++it;
- }
- }
+ /* do something - if feature (first token in tree) is in fact enabled,
+ * make tokens listed afterwards into attributes. i.e.: for
+ * [cfg_attr(feature = "wow", wow1, wow2)], if "wow" is true, then add
+ * attributes [wow1] and [wow2] to attribute list. This can also be
+ * recursive, so check for expanded attributes being recursive and
+ * possibly recursively call the expand_attrs? */
+ }
+ else
+ {
+ i++;
+ }
}
+ attrs.shrink_to_fit ();
+}
- void MacroExpander::expand_crate() {
- /* fill macro/decorator map from init list? not sure where init list comes
- * from? */
+void
+MacroExpander::expand_crate ()
+{
+ /* fill macro/decorator map from init list? not sure where init list comes
+ * from? */
- // expand crate attributes
- expand_attrs_cfgattr(crate.inner_attrs);
+ // TODO: does cfg apply for inner attributes? research.
+ // the apparent answer (from playground test) is yes
- // expand module attributes?
+ // expand crate cfg_attr attributes
+ expand_cfg_attrs (crate.inner_attrs);
- // expand module tree recursively
+ if (fails_cfg (crate.inner_attrs))
+ {
+ // basically, delete whole crate
+ crate.strip_crate ();
+ // TODO: maybe create warning here? probably not desired behaviour
+ }
+ // expand module attributes?
+
+ // expand attributes recursively and strip items if required
+ AttrVisitor attr_visitor (*this);
+ auto &items = crate.items;
+ for (int i = 0; i < items.size ();)
+ {
+ auto &item = items[i];
- // post-process
+ // mark for stripping if required
+ item->accept_vis (attr_visitor);
- // extract exported macros?
+ if (item->is_marked_for_strip ())
+ items.erase (items.begin () + i);
+ else
+ i++;
}
+ // TODO: should recursive attribute and macro expansion be done in the same
+ // transversal? Or in separate ones like currently?
+
+ // expand module tree recursively
+
+ // post-process
+
+ // extract exported macros?
+}
} // namespace Rust
diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h
index 92cb06d..a0c1a076 100644
--- a/gcc/rust/expand/rust-macro-expand.h
+++ b/gcc/rust/expand/rust-macro-expand.h
@@ -15,7 +15,7 @@ class MacroInvocation;
struct ExpansionCfg
{
// features?
- unsigned int recursion_limit; // TODO: determine default recursion limit
+ unsigned int recursion_limit = 50; // TODO: determine default recursion limit
// trace macros?
// should test?
// more default stuff?
@@ -27,7 +27,8 @@ struct MacroExpander
ExpansionCfg cfg;
unsigned int expansion_depth = 0;
- MacroExpander (AST::Crate &crate, ExpansionCfg cfg) : cfg (cfg), crate (crate)
+ MacroExpander (AST::Crate &crate, ExpansionCfg cfg, Session &session)
+ : cfg (cfg), crate (crate), session (session)
{}
~MacroExpander () = default;
@@ -40,11 +41,15 @@ struct MacroExpander
// should this be public or private?
void expand_invoc (std::unique_ptr<AST::MacroInvocation> &invoc);
+ void expand_cfg_attrs (std::vector<AST::Attribute> &attrs);
+ bool fails_cfg (std::vector<AST::Attribute> &attr);
+
/* TODO: make it extend ASTVisitor so that individual items can be accessed
* properly? */
private:
AST::Crate &crate;
+ Session &session;
};
} // namespace Rust
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 4d54242..187f821 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -464,6 +464,7 @@ Parser<ManagedTokenSource>::parse_inner_attributes ()
}
}
+ inner_attributes.shrink_to_fit ();
return inner_attributes;
}
@@ -522,7 +523,27 @@ Parser<ManagedTokenSource>::parse_attribute_body ()
return AST::Attribute (std::move (attr_path), std::move (attr_input), locus);
}
-// Parses a SimplePath AST node
+/* Determines whether token is a valid simple path segment. This does not
+ * include scope resolution operators. */
+inline bool
+is_simple_path_segment (TokenId id)
+{
+ switch (id)
+ {
+ case IDENTIFIER:
+ case SUPER:
+ case SELF:
+ case CRATE:
+ return true;
+ case DOLLAR_SIGN:
+ // assume that dollar sign leads to $crate
+ return true;
+ default:
+ return false;
+ }
+}
+
+// Parses a SimplePath AST node, if it exists. Does nothing otherwise.
template <typename ManagedTokenSource>
AST::SimplePath
Parser<ManagedTokenSource>::parse_simple_path ()
@@ -530,6 +551,11 @@ Parser<ManagedTokenSource>::parse_simple_path ()
bool has_opening_scope_resolution = false;
Location locus = Linemap::unknown_location ();
+ // don't parse anything if not a path upfront
+ if (!is_simple_path_segment (lexer.peek_token ()->get_id ())
+ && !is_simple_path_segment (lexer.peek_token (1)->get_id ()))
+ return AST::SimplePath::create_empty ();
+
/* Checks for opening scope resolution (i.e. global scope fully-qualified
* path) */
if (lexer.peek_token ()->get_id () == SCOPE_RESOLUTION)
@@ -585,6 +611,8 @@ Parser<ManagedTokenSource>::parse_simple_path ()
return AST::SimplePath (std::move (segments), has_opening_scope_resolution,
locus);
+ /* TODO: now that is_simple_path_segment exists, could probably start
+ * actually making errors upon parse failure of segments and whatever */
}
/* Parses a single SimplePathSegment (does not handle the scope resolution
@@ -603,22 +631,21 @@ Parser<ManagedTokenSource>::parse_simple_path_segment ()
case SUPER:
lexer.skip_token ();
- return AST::SimplePathSegment (std::string ("super"), t->get_locus ());
+ return AST::SimplePathSegment ("super", t->get_locus ());
case SELF:
lexer.skip_token ();
- return AST::SimplePathSegment (std::string ("self"), t->get_locus ());
+ return AST::SimplePathSegment ("self", t->get_locus ());
case CRATE:
lexer.skip_token ();
- return AST::SimplePathSegment (std::string ("crate"), t->get_locus ());
+ return AST::SimplePathSegment ("crate", t->get_locus ());
case DOLLAR_SIGN:
if (lexer.peek_token (1)->get_id () == CRATE)
{
lexer.skip_token (1);
- return AST::SimplePathSegment (std::string ("$crate"),
- t->get_locus ());
+ return AST::SimplePathSegment ("$crate", t->get_locus ());
}
gcc_fallthrough ();
default:
@@ -652,25 +679,25 @@ Parser<ManagedTokenSource>::parse_path_ident_segment ()
case SUPER:
lexer.skip_token ();
- return AST::PathIdentSegment (std::string ("super"));
+ return AST::PathIdentSegment ("super");
case SELF:
lexer.skip_token ();
- return AST::PathIdentSegment (std::string ("self"));
+ return AST::PathIdentSegment ("self");
case SELF_ALIAS:
lexer.skip_token ();
- return AST::PathIdentSegment (std::string ("Self"));
+ return AST::PathIdentSegment ("Self");
case CRATE:
lexer.skip_token ();
- return AST::PathIdentSegment (std::string ("crate"));
+ return AST::PathIdentSegment ("crate");
case DOLLAR_SIGN:
if (lexer.peek_token (1)->get_id () == CRATE)
{
lexer.skip_token (1);
- return AST::PathIdentSegment (std::string ("$crate"));
+ return AST::PathIdentSegment ("$crate");
}
gcc_fallthrough ();
default:
@@ -962,6 +989,7 @@ Parser<ManagedTokenSource>::parse_items ()
}
}
+ items.shrink_to_fit ();
return items;
}
@@ -1073,6 +1101,7 @@ Parser<ManagedTokenSource>::parse_outer_attributes ()
}
}
+ outer_attributes.shrink_to_fit ();
return outer_attributes;
/* TODO: this shares basically all code with parse_inner_attributes except
@@ -1262,8 +1291,7 @@ Parser<ManagedTokenSource>::parse_macro_item (
/* dodgy way of detecting macro due to weird context-dependence thing.
* probably can be improved */
// TODO: ensure that string compare works properly
- if (t->get_id () == IDENTIFIER
- && t->get_str () == std::string ("macro_rules"))
+ if (t->get_id () == IDENTIFIER && t->get_str () == "macro_rules")
{
return parse_macro_rules_def (std::move (outer_attrs));
}
@@ -2078,7 +2106,7 @@ Parser<ManagedTokenSource>::parse_extern_crate (
lexer.skip_token ();
break;
case SELF:
- crate_name = std::string ("self");
+ crate_name = "self";
lexer.skip_token ();
break;
default:
@@ -2117,7 +2145,7 @@ Parser<ManagedTokenSource>::parse_extern_crate (
lexer.skip_token ();
break;
case UNDERSCORE:
- as_name = std::string ("_");
+ as_name = "_";
lexer.skip_token ();
break;
default:
@@ -2213,17 +2241,14 @@ Parser<ManagedTokenSource>::parse_use_tree ()
{
// has no path, so must be glob or nested tree UseTree type
- /* due to implementation issues, parsing simple path removes any trailing
- * scope resolutions (or any, actually, if the use tree has no path
- * given), so we'll just assume that there's one there. */
- // Check anyway, but optional.
+ bool is_global = false;
+
+ // check for global scope resolution operator
if (lexer.peek_token ()->get_id () == SCOPE_RESOLUTION)
{
lexer.skip_token ();
+ is_global = true;
}
- /* Note that this implementation issue also makes it impossible to
- * determine at the moment whether the tree has GLOBAL or NO_PATH path
- * type. */
const_TokenPtr t = lexer.peek_token ();
switch (t->get_id ())
@@ -2232,11 +2257,14 @@ Parser<ManagedTokenSource>::parse_use_tree ()
// glob UseTree type
lexer.skip_token ();
- // TODO: find way to determine whether GLOBAL or NO_PATH path type -
- // placeholder
- return std::unique_ptr<AST::UseTreeGlob> (
- new AST::UseTreeGlob (AST::UseTreeGlob::NO_PATH,
- AST::SimplePath::create_empty (), locus));
+ if (is_global)
+ return std::unique_ptr<AST::UseTreeGlob> (
+ new AST::UseTreeGlob (AST::UseTreeGlob::GLOBAL,
+ AST::SimplePath::create_empty (), locus));
+ else
+ return std::unique_ptr<AST::UseTreeGlob> (
+ new AST::UseTreeGlob (AST::UseTreeGlob::NO_PATH,
+ AST::SimplePath::create_empty (), locus));
case LEFT_CURLY: {
// nested tree UseTree type
lexer.skip_token ();
@@ -2255,11 +2283,9 @@ Parser<ManagedTokenSource>::parse_use_tree ()
use_trees.push_back (std::move (use_tree));
if (lexer.peek_token ()->get_id () != COMMA)
- {
- break;
- }
- lexer.skip_token ();
+ break;
+ lexer.skip_token ();
t = lexer.peek_token ();
}
@@ -2270,24 +2296,30 @@ Parser<ManagedTokenSource>::parse_use_tree ()
return nullptr;
}
- /* TODO: find way to determine whether GLOBAL or NO_PATH path type -
- * placeholder */
- return std::unique_ptr<AST::UseTreeList> (
- new AST::UseTreeList (AST::UseTreeList::NO_PATH,
- AST::SimplePath::create_empty (),
- std::move (use_trees), locus));
+ if (is_global)
+ return std::unique_ptr<AST::UseTreeList> (
+ new AST::UseTreeList (AST::UseTreeList::GLOBAL,
+ AST::SimplePath::create_empty (),
+ std::move (use_trees), locus));
+ else
+ return std::unique_ptr<AST::UseTreeList> (
+ new AST::UseTreeList (AST::UseTreeList::NO_PATH,
+ AST::SimplePath::create_empty (),
+ std::move (use_trees), locus));
}
case AS:
// this is not allowed
- rust_error_at (t->get_locus (),
- "use declaration with rebind %<as%> requires a valid "
- "simple path - none found");
+ rust_error_at (
+ t->get_locus (),
+ "use declaration with rebind %<as%> requires a valid simple path - "
+ "none found");
skip_after_semicolon ();
return nullptr;
default:
rust_error_at (t->get_locus (),
"unexpected token %qs in use tree with no valid "
- "simple path (i.e. list or glob use tree)",
+ "simple path (i.e. list"
+ " or glob use tree)",
t->get_token_description ());
skip_after_semicolon ();
return nullptr;
@@ -2296,7 +2328,8 @@ Parser<ManagedTokenSource>::parse_use_tree ()
else
{
/* Due to aforementioned implementation issues, the trailing :: token is
- * consumed by the path, so it can not be used as a disambiguator. */
+ * consumed by the path, so it can not be used as a disambiguator.
+ * NOPE, not true anymore - TODO what are the consequences of this? */
const_TokenPtr t = lexer.peek_token ();
switch (t->get_id ())
@@ -2327,11 +2360,9 @@ Parser<ManagedTokenSource>::parse_use_tree ()
use_trees.push_back (std::move (use_tree));
if (lexer.peek_token ()->get_id () != COMMA)
- {
- break;
- }
- lexer.skip_token ();
+ break;
+ lexer.skip_token ();
t = lexer.peek_token ();
}
@@ -2368,14 +2399,13 @@ Parser<ManagedTokenSource>::parse_use_tree ()
return std::unique_ptr<AST::UseTreeRebind> (
new AST::UseTreeRebind (AST::UseTreeRebind::WILDCARD,
- std::move (path), locus,
- std::string ("_")));
+ std::move (path), locus, "_"));
default:
- rust_error_at (t->get_locus (),
- "unexpected token %qs in use tree with as "
- "clause - expected "
- "identifier or %<_%>",
- t->get_token_description ());
+ rust_error_at (
+ t->get_locus (),
+ "unexpected token %qs in use tree with as clause - expected "
+ "identifier or %<_%>",
+ t->get_token_description ());
skip_after_semicolon ();
return nullptr;
}
@@ -2442,9 +2472,8 @@ Parser<ManagedTokenSource>::parse_function (
// parse function parameters (only if next token isn't right paren)
std::vector<AST::FunctionParam> function_params;
if (lexer.peek_token ()->get_id () != RIGHT_PAREN)
- {
- function_params = parse_function_params ();
- }
+ function_params
+ = parse_function_params ([] (TokenId id) { return id == RIGHT_PAREN; });
if (!skip_token (RIGHT_PAREN))
{
@@ -2745,6 +2774,7 @@ Parser<ManagedTokenSource>::parse_generic_params ()
std::make_move_iterator(type_params.end()));
}*/
+ generic_params.shrink_to_fit ();
return generic_params;
}
@@ -2902,6 +2932,7 @@ Parser<ManagedTokenSource>::parse_generic_params (EndTokenPred is_end_token)
std::make_move_iterator(type_params.end()));
}*/
+ generic_params.shrink_to_fit ();
return generic_params;
}
@@ -3149,6 +3180,7 @@ Parser<ManagedTokenSource>::parse_type_params ()
lexer.skip_token ();
}
+ type_params.shrink_to_fit ();
return type_params;
}
@@ -3180,6 +3212,7 @@ Parser<ManagedTokenSource>::parse_type_params (EndTokenPred is_end_token)
lexer.skip_token ();
}
+ type_params.shrink_to_fit ();
return type_params;
/* TODO: this shares most code with parse_lifetime_params - good place to use
* template (i.e. parse_non_ptr_sequence if doable) */
@@ -3236,24 +3269,24 @@ Parser<ManagedTokenSource>::parse_type_param ()
std::move (outer_attr)));
}
-// Parses regular (i.e. non-generic) parameters in functions or methods.
+/* Parses regular (i.e. non-generic) parameters in functions or methods. Also
+ * has end token handling. */
template <typename ManagedTokenSource>
+template <typename EndTokenPred>
std::vector<AST::FunctionParam>
-Parser<ManagedTokenSource>::parse_function_params ()
+Parser<ManagedTokenSource>::parse_function_params (EndTokenPred is_end_token)
{
std::vector<AST::FunctionParam> params;
- // HACK: return early if RIGHT_PAREN is found
- if (lexer.peek_token ()->get_id () == RIGHT_PAREN)
- {
- return params;
- }
+ if (is_end_token (lexer.peek_token ()->get_id ()))
+ return params;
AST::FunctionParam initial_param = parse_function_param ();
// Return empty parameter list if no parameter there
if (initial_param.is_error ())
{
+ // TODO: is this an error?
return params;
}
@@ -3268,13 +3301,9 @@ Parser<ManagedTokenSource>::parse_function_params ()
// skip comma if applies
lexer.skip_token ();
- /* HACK: break if next token is a right (closing) paren - this is not
- * strictly true via grammar rule but seems to be true in practice (i.e.
- * with trailing comma). */
- if (lexer.peek_token ()->get_id () == RIGHT_PAREN)
- {
- break;
- }
+ // TODO: strictly speaking, shouldn't there be no trailing comma?
+ if (is_end_token (lexer.peek_token ()->get_id ()))
+ break;
// now, as right paren would break, function param is required
AST::FunctionParam param = parse_function_param ();
@@ -3291,6 +3320,7 @@ Parser<ManagedTokenSource>::parse_function_params ()
t = lexer.peek_token ();
}
+ params.shrink_to_fit ();
return params;
}
@@ -3300,6 +3330,10 @@ template <typename ManagedTokenSource>
AST::FunctionParam
Parser<ManagedTokenSource>::parse_function_param ()
{
+ // parse outer attributes if they exist
+ std::vector<AST::Attribute> outer_attrs = parse_outer_attributes ();
+
+ // TODO: should saved location be at start of outer attributes or pattern?
Location locus = lexer.peek_token ()->get_locus ();
std::unique_ptr<AST::Pattern> param_pattern = parse_pattern ();
@@ -3324,7 +3358,7 @@ Parser<ManagedTokenSource>::parse_function_param ()
}
return AST::FunctionParam (std::move (param_pattern), std::move (param_type),
- locus);
+ std::move (outer_attrs), locus);
}
/* Parses a function or method return type syntactical construction. Also
@@ -3334,9 +3368,8 @@ std::unique_ptr<AST::Type>
Parser<ManagedTokenSource>::parse_function_return_type ()
{
if (lexer.peek_token ()->get_id () != RETURN_TYPE)
- {
- return nullptr;
- }
+ return nullptr;
+
// skip return type, as it now obviously exists
lexer.skip_token ();
@@ -3391,6 +3424,7 @@ Parser<ManagedTokenSource>::parse_where_clause ()
t = lexer.peek_token ();
}
+ where_clause_items.shrink_to_fit ();
return AST::WhereClause (std::move (where_clause_items));
}
@@ -3542,8 +3576,8 @@ Parser<ManagedTokenSource>::parse_type_param_bounds ()
return type_param_bounds;
}
-// Parses type parameter bounds in where clause or generic arguments, with end
-// token handling.
+/* Parses type parameter bounds in where clause or generic arguments, with end
+ * token handling. */
template <typename ManagedTokenSource>
template <typename EndTokenPred>
std::vector<std::unique_ptr<AST::TypeParamBound> >
@@ -4092,6 +4126,7 @@ Parser<ManagedTokenSource>::parse_tuple_fields ()
t = lexer.peek_token ();
}
+ fields.shrink_to_fit ();
return fields;
// TODO: this shares basically all code with function params and struct fields
@@ -4196,6 +4231,7 @@ Parser<ManagedTokenSource>::parse_enum_items ()
items.push_back (std::move (item));
}
+ items.shrink_to_fit ();
return items;
/* TODO: use template if doable (parse_non_ptr_sequence) */
@@ -4237,6 +4273,7 @@ Parser<ManagedTokenSource>::parse_enum_items (EndTokenPred is_end_tok)
items.push_back (std::move (item));
}
+ items.shrink_to_fit ();
return items;
/* TODO: use template if doable (parse_non_ptr_sequence) */
@@ -4530,6 +4567,9 @@ Parser<ManagedTokenSource>::parse_trait (
return nullptr;
}
+ // parse inner attrs (if they exist)
+ std::vector<AST::Attribute> inner_attrs = parse_inner_attributes ();
+
// parse trait items
std::vector<std::unique_ptr<AST::TraitItem> > trait_items;
@@ -4555,11 +4595,12 @@ Parser<ManagedTokenSource>::parse_trait (
return nullptr;
}
+ trait_items.shrink_to_fit ();
return std::unique_ptr<AST::Trait> (
new AST::Trait (std::move (ident), is_unsafe, std::move (generic_params),
std::move (type_param_bounds), std::move (where_clause),
std::move (trait_items), std::move (vis),
- std::move (outer_attrs), locus));
+ std::move (outer_attrs), std::move (inner_attrs), locus));
}
// Parses a trait item used inside traits (not trait, the Item).
@@ -4613,27 +4654,26 @@ Parser<ManagedTokenSource>::parse_trait_item ()
return nullptr;
}
- // now for function vs method disambiguation - method has opening "self"
- // param
+ /* now for function vs method disambiguation - method has opening "self"
+ * param */
AST::SelfParam self_param = parse_self_param ();
- // FIXME: ensure that self param doesn't accidently consume tokens for a
- // function
+ /* FIXME: ensure that self param doesn't accidently consume tokens for a
+ * function */
bool is_method = false;
if (!self_param.is_error ())
{
is_method = true;
- // skip comma so function and method regular params can be parsed in
- // same way
+ /* skip comma so function and method regular params can be parsed in
+ * same way */
if (lexer.peek_token ()->get_id () == COMMA)
- {
- lexer.skip_token ();
- }
+ lexer.skip_token ();
}
// parse trait function params
std::vector<AST::FunctionParam> function_params
- = parse_function_params ();
+ = parse_function_params (
+ [] (TokenId id) { return id == RIGHT_PAREN; });
if (!skip_token (RIGHT_PAREN))
{
@@ -4914,6 +4954,8 @@ Parser<ManagedTokenSource>::parse_impl (AST::Visibility vis,
// DEBUG
fprintf (stderr, "successfully parsed inherent impl\n");
+ impl_items.shrink_to_fit ();
+
return std::unique_ptr<AST::InherentImpl> (new AST::InherentImpl (
std::move (impl_items), std::move (generic_params), std::move (type),
std::move (where_clause), std::move (vis), std::move (inner_attrs),
@@ -4987,6 +5029,8 @@ Parser<ManagedTokenSource>::parse_impl (AST::Visibility vis,
// DEBUG
fprintf (stderr, "successfully parsed trait impl\n");
+ impl_items.shrink_to_fit ();
+
return std::unique_ptr<AST::TraitImpl> (
new AST::TraitImpl (std::move (type_path), is_unsafe, has_exclam,
std::move (impl_items), std::move (generic_params),
@@ -5138,24 +5182,23 @@ Parser<ManagedTokenSource>::parse_inherent_impl_function_or_method (
// now for function vs method disambiguation - method has opening "self" param
AST::SelfParam self_param = parse_self_param ();
- // FIXME: ensure that self param doesn't accidently consume tokens for a
- // function one idea is to lookahead up to 4 tokens to see whether self is one
- // of them
+ /* FIXME: ensure that self param doesn't accidently consume tokens for a
+ * function one idea is to lookahead up to 4 tokens to see whether self is one
+ * of them */
bool is_method = false;
if (!self_param.is_error ())
{
is_method = true;
- // skip comma so function and method regular params can be parsed in same
- // way
+ /* skip comma so function and method regular params can be parsed in same
+ * way */
if (lexer.peek_token ()->get_id () == COMMA)
- {
- lexer.skip_token ();
- }
+ lexer.skip_token ();
}
// parse trait function params
- std::vector<AST::FunctionParam> function_params = parse_function_params ();
+ std::vector<AST::FunctionParam> function_params
+ = parse_function_params ([] (TokenId id) { return id == RIGHT_PAREN; });
if (!skip_token (RIGHT_PAREN))
{
@@ -5400,7 +5443,8 @@ Parser<ManagedTokenSource>::parse_trait_impl_function_or_method (
std::vector<AST::FunctionParam> function_params;
if (lexer.peek_token ()->get_id () != RIGHT_PAREN)
{
- function_params = parse_function_params ();
+ function_params
+ = parse_function_params ([] (TokenId id) { return id == RIGHT_PAREN; });
if (function_params.empty ())
{
@@ -5535,6 +5579,8 @@ Parser<ManagedTokenSource>::parse_extern_block (
return nullptr;
}
+ extern_items.shrink_to_fit ();
+
return std::unique_ptr<AST::ExternBlock> (
new AST::ExternBlock (std::move (abi), std::move (extern_items),
std::move (vis), std::move (inner_attrs),
@@ -5632,55 +5678,53 @@ Parser<ManagedTokenSource>::parse_external_item ()
// parse parameters
std::vector<AST::NamedFunctionParam> function_params;
bool is_variadic = false;
+ std::vector<AST::Attribute> variadic_attrs;
const_TokenPtr t = lexer.peek_token ();
while (t->get_id () != RIGHT_PAREN)
{
- AST::NamedFunctionParam param = parse_named_function_param ();
+ std::vector<AST::Attribute> maybe_variadic_attrs
+ = parse_outer_attributes ();
+ if (lexer.peek_token ()->get_id () == ELLIPSIS)
+ {
+ // variadic - use attrs for this
+ lexer.skip_token ();
+ is_variadic = true;
+ variadic_attrs = std::move (maybe_variadic_attrs);
+ t = lexer.peek_token ();
+
+ if (t->get_id () != RIGHT_PAREN)
+ {
+ rust_error_at (t->get_locus (),
+ "expected right parentheses after variadic "
+ "in named function "
+ "parameters, found %qs",
+ t->get_token_description ());
+ skip_after_semicolon ();
+ return nullptr;
+ }
+ break;
+ }
+
+ AST::NamedFunctionParam param
+ = parse_named_function_param (std::move (maybe_variadic_attrs));
if (param.is_error ())
{
- // is this an error? probably
rust_error_at (t->get_locus (),
"could not parse named function parameter in "
"external function");
skip_after_semicolon ();
return nullptr;
}
-
function_params.push_back (std::move (param));
- t = lexer.peek_token ();
- if (t->get_id () != COMMA)
- {
- if (t->get_id () != RIGHT_PAREN)
- {
- rust_error_at (t->get_locus (),
- "expected comma or right parentheses in "
- "named function parameters, found %qs",
- t->get_token_description ());
- }
- else
- {
- // end of loop
- break;
- }
- }
+ if (lexer.peek_token ()->get_id () != COMMA)
+ break;
+
// skip comma
lexer.skip_token ();
-
t = lexer.peek_token ();
-
- // parse variadic ... if it exists
- if (t->get_id () == ELLIPSIS
- && lexer.peek_token (1)->get_id () == RIGHT_PAREN)
- {
- lexer.skip_token ();
-
- is_variadic = true;
-
- t = lexer.peek_token ();
- }
}
if (!skip_token (RIGHT_PAREN))
@@ -5701,11 +5745,14 @@ Parser<ManagedTokenSource>::parse_external_item ()
return nullptr;
}
+ function_params.shrink_to_fit ();
+
return std::unique_ptr<AST::ExternalFunctionItem> (
new AST::ExternalFunctionItem (
std::move (ident), std::move (generic_params),
std::move (return_type), std::move (where_clause),
- std::move (function_params), is_variadic, std::move (vis),
+ std::move (function_params), is_variadic,
+ std::move (variadic_attrs), std::move (vis),
std::move (outer_attrs), locus));
}
default:
@@ -5722,10 +5769,11 @@ Parser<ManagedTokenSource>::parse_external_item ()
* identifier). */
template <typename ManagedTokenSource>
AST::NamedFunctionParam
-Parser<ManagedTokenSource>::parse_named_function_param ()
+Parser<ManagedTokenSource>::parse_named_function_param (
+ std::vector<AST::Attribute> outer_attrs)
{
// parse identifier/_
- Identifier name;
+ std::string name;
const_TokenPtr t = lexer.peek_token ();
switch (t->get_id ())
@@ -5760,7 +5808,8 @@ Parser<ManagedTokenSource>::parse_named_function_param ()
return AST::NamedFunctionParam::create_error ();
}
- return AST::NamedFunctionParam (std::move (name), std::move (param_type));
+ return AST::NamedFunctionParam (std::move (name), std::move (param_type),
+ std::move (outer_attrs));
}
// Parses a statement (will further disambiguate any statement).
@@ -6231,6 +6280,7 @@ Parser<ManagedTokenSource>::parse_type_path_function ()
// parse optional return type
std::unique_ptr<AST::Type> return_type = parse_function_return_type ();
+ inputs.shrink_to_fit ();
return AST::TypePathFunction (std::move (inputs), std::move (return_type));
}
@@ -6403,6 +6453,8 @@ Parser<ManagedTokenSource>::parse_qualified_path_in_expression (
t = lexer.peek_token ();
}
+ segments.shrink_to_fit ();
+
// FIXME: outer attr parsing
return AST::QualifiedPathInExpression (std::move (qual_path_type),
std::move (segments), locus,
@@ -6678,7 +6730,8 @@ Parser<ManagedTokenSource>::parse_method ()
lexer.skip_token ();
// parse function parameters
- std::vector<AST::FunctionParam> function_params = parse_function_params ();
+ std::vector<AST::FunctionParam> function_params
+ = parse_function_params ([] (TokenId id) { return id == RIGHT_PAREN; });
if (!skip_token (RIGHT_PAREN))
{
@@ -7077,6 +7130,8 @@ Parser<ManagedTokenSource>::parse_block_expr (
// grammar allows for empty block expressions
+ stmts.shrink_to_fit ();
+
return std::unique_ptr<AST::BlockExpr> (
new AST::BlockExpr (std::move (stmts), std::move (expr),
std::move (inner_attrs), std::move (outer_attrs),
@@ -7165,6 +7220,7 @@ Parser<ManagedTokenSource>::parse_closure_expr (
t = lexer.peek_token ();
}
+ params.shrink_to_fit ();
break;
default:
rust_error_at (t->get_locus (),
@@ -7282,12 +7338,12 @@ Parser<ManagedTokenSource>::parse_literal_expr (
// use true and false keywords rather than "bool literal" Rust terminology
case TRUE_LITERAL:
type = AST::Literal::BOOL;
- literal_value = std::string ("true");
+ literal_value = "true";
lexer.skip_token ();
break;
case FALSE_LITERAL:
type = AST::Literal::BOOL;
- literal_value = std::string ("false");
+ literal_value = "false";
lexer.skip_token ();
break;
default:
@@ -8419,6 +8475,8 @@ Parser<ManagedTokenSource>::parse_array_expr (
return nullptr;
}
+ skip_token (RIGHT_SQUARE);
+
std::unique_ptr<AST::ArrayElemsCopied> copied_array_elems (
new AST::ArrayElemsCopied (std::move (initial_expr),
std::move (copy_amount)));
@@ -8435,6 +8493,8 @@ Parser<ManagedTokenSource>::parse_array_expr (
exprs.push_back (std::move (initial_expr));
exprs.shrink_to_fit ();
+ skip_token (RIGHT_SQUARE);
+
std::unique_ptr<AST::ArrayElemsValues> array_elems (
new AST::ArrayElemsValues (std::move (exprs)));
return std::unique_ptr<AST::ArrayExpr> (
@@ -8500,6 +8560,8 @@ template <typename ManagedTokenSource>
AST::ClosureParam
Parser<ManagedTokenSource>::parse_closure_param ()
{
+ std::vector<AST::Attribute> outer_attrs = parse_outer_attributes ();
+
// parse pattern (which is required)
std::unique_ptr<AST::Pattern> pattern = parse_pattern ();
if (pattern == nullptr)
@@ -8525,7 +8587,8 @@ Parser<ManagedTokenSource>::parse_closure_param ()
}
}
- return AST::ClosureParam (std::move (pattern), std::move (type));
+ return AST::ClosureParam (std::move (pattern), std::move (type),
+ std::move (outer_attrs));
}
// Parses a grouped or tuple expression (disambiguates).
@@ -9191,7 +9254,8 @@ Parser<ManagedTokenSource>::parse_for_prefixed_type ()
// Parses a maybe named param used in bare function types.
template <typename ManagedTokenSource>
AST::MaybeNamedParam
-Parser<ManagedTokenSource>::parse_maybe_named_param ()
+Parser<ManagedTokenSource>::parse_maybe_named_param (
+ std::vector<AST::Attribute> outer_attrs)
{
/* Basically guess that param is named if first token is identifier or
* underscore and second token is semicolon. This should probably have no
@@ -9228,7 +9292,7 @@ Parser<ManagedTokenSource>::parse_maybe_named_param ()
}
return AST::MaybeNamedParam (std::move (name), kind, std::move (type),
- current->get_locus ());
+ std::move (outer_attrs), current->get_locus ());
}
/* Parses a bare function type (with the given for lifetimes for convenience -
@@ -9244,63 +9308,62 @@ Parser<ManagedTokenSource>::parse_bare_function_type (
AST::FunctionQualifiers qualifiers = parse_function_qualifiers ();
if (!skip_token (FN_TOK))
- {
- return nullptr;
- }
+ return nullptr;
if (!skip_token (LEFT_PAREN))
- {
- return nullptr;
- }
+ return nullptr;
// parse function params, if they exist
std::vector<AST::MaybeNamedParam> params;
bool is_variadic = false;
+ std::vector<AST::Attribute> variadic_attrs;
+
const_TokenPtr t = lexer.peek_token ();
while (t->get_id () != RIGHT_PAREN)
{
- // handle ellipsis (only if next character is right paren)
- if (t->get_id () == ELLIPSIS)
+ std::vector<AST::Attribute> temp_attrs = parse_outer_attributes ();
+
+ if (lexer.peek_token ()->get_id () == ELLIPSIS)
{
- if (lexer.peek_token (1)->get_id () == RIGHT_PAREN)
- {
- lexer.skip_token ();
- is_variadic = true;
- break;
- }
- else
+ lexer.skip_token ();
+ is_variadic = true;
+ variadic_attrs = std::move (temp_attrs);
+
+ t = lexer.peek_token ();
+
+ if (t->get_id () != RIGHT_PAREN)
{
rust_error_at (t->get_locus (),
- "ellipsis (for variadic) can only go at end of "
- "bare function type");
+ "expected right parentheses after variadic in "
+ "maybe named function "
+ "parameters, found %qs",
+ t->get_token_description ());
return nullptr;
}
+
+ break;
}
- // parse required param
- AST::MaybeNamedParam param = parse_maybe_named_param ();
+ AST::MaybeNamedParam param
+ = parse_maybe_named_param (std::move (temp_attrs));
if (param.is_error ())
{
rust_error_at (
- t->get_locus (),
+ lexer.peek_token ()->get_locus (),
"failed to parse maybe named param in bare function type");
return nullptr;
}
params.push_back (std::move (param));
if (lexer.peek_token ()->get_id () != COMMA)
- {
- break;
- }
- lexer.skip_token ();
+ break;
+ lexer.skip_token ();
t = lexer.peek_token ();
}
if (!skip_token (RIGHT_PAREN))
- {
- return nullptr;
- }
+ return nullptr;
// bare function return type, if exists
std::unique_ptr<AST::TypeNoBounds> return_type = nullptr;
@@ -9319,9 +9382,11 @@ Parser<ManagedTokenSource>::parse_bare_function_type (
}
}
- return std::unique_ptr<AST::BareFunctionType> (new AST::BareFunctionType (
- std::move (for_lifetimes), std::move (qualifiers), std::move (params),
- is_variadic, std::move (return_type), best_try_locus));
+ return std::unique_ptr<AST::BareFunctionType> (
+ new AST::BareFunctionType (std::move (for_lifetimes),
+ std::move (qualifiers), std::move (params),
+ is_variadic, std::move (variadic_attrs),
+ std::move (return_type), best_try_locus));
}
// Parses a reference type (mutable or immutable, with given lifetime).
@@ -10136,6 +10201,14 @@ Parser<ManagedTokenSource>::parse_pattern ()
// tuple struct
lexer.skip_token ();
+ // check if empty tuple
+ if (lexer.peek_token ()->get_id () == RIGHT_PAREN)
+ {
+ lexer.skip_token ();
+ return std::unique_ptr<AST::TupleStructPattern> (
+ new AST::TupleStructPattern (std::move (path), nullptr));
+ }
+
// parse items
std::unique_ptr<AST::TupleStructItems> items
= parse_tuple_struct_items ();
@@ -10560,6 +10633,14 @@ Parser<ManagedTokenSource>::parse_ident_leading_pattern ()
// DEBUG
fprintf (stderr, "parsing tuple struct pattern\n");
+ // check if empty tuple
+ if (lexer.peek_token ()->get_id () == RIGHT_PAREN)
+ {
+ lexer.skip_token ();
+ return std::unique_ptr<AST::TupleStructPattern> (
+ new AST::TupleStructPattern (std::move (path), nullptr));
+ }
+
// parse items
std::unique_ptr<AST::TupleStructItems> items
= parse_tuple_struct_items ();
@@ -10802,53 +10883,48 @@ Parser<ManagedTokenSource>::parse_struct_pattern_elems ()
{
std::vector<std::unique_ptr<AST::StructPatternField> > fields;
+ std::vector<AST::Attribute> etc_attrs;
+ bool has_etc = false;
+
// try parsing struct pattern fields
const_TokenPtr t = lexer.peek_token ();
- while (t->get_id () != RIGHT_CURLY && t->get_id () != DOT_DOT)
+ while (t->get_id () != RIGHT_CURLY)
{
- std::unique_ptr<AST::StructPatternField> field
- = parse_struct_pattern_field ();
- if (field == nullptr)
- {
- // TODO: should this be an error?
- // assuming that this means that it is a struct pattern etc instead
-
- // DEBUG
- fprintf (
- stderr,
- "failed to parse struct pattern field - breaking from loop\n");
+ std::vector<AST::Attribute> outer_attrs = parse_outer_attributes ();
+ // parse etc (must be last in struct pattern, so breaks)
+ if (lexer.peek_token ()->get_id () == DOT_DOT)
+ {
+ lexer.skip_token ();
+ etc_attrs = std::move (outer_attrs);
+ has_etc = true;
break;
}
- fields.push_back (std::move (field));
-
- // DEBUG
- fprintf (stderr, "successfully pushed back a struct pattern field\n");
-
- if (lexer.peek_token ()->get_id () != COMMA)
+ std::unique_ptr<AST::StructPatternField> field
+ = parse_struct_pattern_field_partial (std::move (outer_attrs));
+ if (field == nullptr)
{
- break;
+ rust_error_at (lexer.peek_token ()->get_locus (),
+ "failed to parse struct pattern field");
+ // skip after somewhere?
+ return AST::StructPatternElements::create_empty ();
}
- lexer.skip_token ();
+ fields.push_back (std::move (field));
- t = lexer.peek_token ();
- }
+ if (lexer.peek_token ()->get_id () != COMMA)
+ break;
- /* FIXME: this method of parsing prevents parsing any outer attributes on the
- * .. - also there seems to be no distinction between having etc and not
- * having etc. */
- if (lexer.peek_token ()->get_id () == DOT_DOT)
- {
+ // skip comma
lexer.skip_token ();
-
- // as no outer attributes
- AST::StructPatternEtc etc = AST::StructPatternEtc::create_empty ();
-
- return AST::StructPatternElements (std::move (fields), std::move (etc));
+ t = lexer.peek_token ();
}
- return AST::StructPatternElements (std::move (fields));
+ if (has_etc)
+ return AST::StructPatternElements (std::move (fields),
+ std::move (etc_attrs));
+ else
+ return AST::StructPatternElements (std::move (fields));
}
/* Parses a struct pattern field (tuple index/pattern, identifier/pattern, or
@@ -10860,6 +10936,16 @@ Parser<ManagedTokenSource>::parse_struct_pattern_field ()
// parse outer attributes (if they exist)
std::vector<AST::Attribute> outer_attrs = parse_outer_attributes ();
+ return parse_struct_pattern_field_partial (std::move (outer_attrs));
+}
+
+/* Parses a struct pattern field (tuple index/pattern, identifier/pattern, or
+ * identifier), with outer attributes passed in. */
+template <typename ManagedTokenSource>
+std::unique_ptr<AST::StructPatternField>
+Parser<ManagedTokenSource>::parse_struct_pattern_field_partial (
+ std::vector<AST::Attribute> outer_attrs)
+{
// branch based on next token
const_TokenPtr t = lexer.peek_token ();
switch (t->get_id ())
@@ -11478,7 +11564,8 @@ Parser<ManagedTokenSource>::parse_struct_expr_field ()
return std::unique_ptr<AST::StructExprFieldIdentifierValue> (
new AST::StructExprFieldIdentifierValue (std::move (ident),
- std::move (expr)));
+ std::move (expr),
+ t->get_locus ()));
}
else
{
@@ -11487,7 +11574,8 @@ Parser<ManagedTokenSource>::parse_struct_expr_field ()
lexer.skip_token ();
return std::unique_ptr<AST::StructExprFieldIdentifier> (
- new AST::StructExprFieldIdentifier (std::move (ident)));
+ new AST::StructExprFieldIdentifier (std::move (ident),
+ t->get_locus ()));
}
case INT_LITERAL: {
// parse tuple index field
@@ -11511,7 +11599,8 @@ Parser<ManagedTokenSource>::parse_struct_expr_field ()
}
return std::unique_ptr<AST::StructExprFieldIndexValue> (
- new AST::StructExprFieldIndexValue (index, std::move (expr)));
+ new AST::StructExprFieldIndexValue (index, std::move (expr),
+ t->get_locus ()));
}
case DOT_DOT:
/* this is a struct base and can't be parsed here, so just return nothing
@@ -11519,10 +11608,11 @@ Parser<ManagedTokenSource>::parse_struct_expr_field ()
return nullptr;
default:
- rust_error_at (t->get_locus (),
- "unrecognised token %qs as first token of struct expr "
- "field - expected identifier or int literal",
- t->get_token_description ());
+ rust_error_at (
+ t->get_locus (),
+ "unrecognised token %qs as first token of struct expr field - "
+ "expected identifier or int literal",
+ t->get_token_description ());
return nullptr;
}
}
@@ -13650,12 +13740,15 @@ Parser<ManagedTokenSource>::parse_tuple_index_expr (
template <typename ManagedTokenSource>
std::unique_ptr<AST::ArrayIndexExpr>
Parser<ManagedTokenSource>::parse_index_expr (
- const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr<AST::Expr> array_expr,
- std::vector<AST::Attribute> outer_attrs, ParseRestrictions restrictions)
+ const_TokenPtr, std::unique_ptr<AST::Expr> array_expr,
+ std::vector<AST::Attribute> outer_attrs, ParseRestrictions)
{
// parse RHS (as tok has already been consumed in parse_expression)
- std::unique_ptr<AST::Expr> index_expr
- = parse_expr (LBP_ARRAY_REF, std::vector<AST::Attribute> (), restrictions);
+ /*std::unique_ptr<AST::Expr> index_expr
+ = parse_expr (LBP_ARRAY_REF, std::vector<AST::Attribute> (),
+ restrictions);*/
+ // TODO: conceptually, should treat [] as brackets, so just parse all expr
+ std::unique_ptr<AST::Expr> index_expr = parse_expr ();
if (index_expr == nullptr)
return nullptr;
@@ -13682,8 +13775,8 @@ Parser<ManagedTokenSource>::parse_field_access_expr (
std::vector<AST::Attribute> outer_attrs,
ParseRestrictions restrictions ATTRIBUTE_UNUSED)
{
- // get field name identifier (assume that this is a field access expr and not
- // say await)
+ /* get field name identifier (assume that this is a field access expr and not
+ * await, for instance) */
const_TokenPtr ident_tok = expect_token (IDENTIFIER);
Identifier ident = ident_tok->get_str ();
@@ -13967,7 +14060,10 @@ Parser<ManagedTokenSource>::parse_struct_expr_struct_partial (
}
/* Parses a struct expr tuple with a path in expression already parsed (but not
- * '(' token). */
+ * '(' token).
+ * FIXME: this currently outputs a call expr, as they cannot be disambiguated.
+ * A better solution would be to just get this to call that function directly.
+ * */
template <typename ManagedTokenSource>
std::unique_ptr<AST::CallExpr>
Parser<ManagedTokenSource>::parse_struct_expr_tuple_partial (
@@ -14261,7 +14357,7 @@ Parser<ManagedTokenSource>::parse_tuple_index_expr_float (
{
// only works on float literals
if (tok->get_id () != FLOAT_LITERAL)
- return nullptr;
+ return nullptr;
// DEBUG:
fprintf (stderr, "exact string form of float: '%s'\n",
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index e2f3a78..7218ebc 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -164,7 +164,8 @@ private:
template <typename EndTokenPred>
std::vector<std::unique_ptr<AST::TypeParam> > parse_type_params (EndTokenPred is_end_token);
std::unique_ptr<AST::TypeParam> parse_type_param ();
- std::vector<AST::FunctionParam> parse_function_params ();
+ template <typename EndTokenPred>
+ std::vector<AST::FunctionParam> parse_function_params (EndTokenPred is_end_token);
AST::FunctionParam parse_function_param ();
std::unique_ptr<AST::Type> parse_function_return_type ();
AST::WhereClause parse_where_clause ();
@@ -230,7 +231,8 @@ private:
parse_extern_block (AST::Visibility vis,
std::vector<AST::Attribute> outer_attrs);
std::unique_ptr<AST::ExternalItem> parse_external_item ();
- AST::NamedFunctionParam parse_named_function_param ();
+ AST::NamedFunctionParam parse_named_function_param (
+ std::vector<AST::Attribute> outer_attrs = std::vector<AST::Attribute> ());
AST::Method parse_method ();
// Expression-related (Pratt parsed)
@@ -543,7 +545,7 @@ private:
std::unique_ptr<AST::Type> parse_paren_prefixed_type ();
std::unique_ptr<AST::TypeNoBounds> parse_paren_prefixed_type_no_bounds ();
std::unique_ptr<AST::Type> parse_for_prefixed_type ();
- AST::MaybeNamedParam parse_maybe_named_param ();
+ AST::MaybeNamedParam parse_maybe_named_param (std::vector<AST::Attribute> outer_attrs);
// Statement-related
std::unique_ptr<AST::Stmt> parse_stmt ();
@@ -573,6 +575,7 @@ private:
std::unique_ptr<AST::TupleStructItems> parse_tuple_struct_items ();
AST::StructPatternElements parse_struct_pattern_elems ();
std::unique_ptr<AST::StructPatternField> parse_struct_pattern_field ();
+ std::unique_ptr<AST::StructPatternField> parse_struct_pattern_field_partial (std::vector<AST::Attribute> outer_attrs);
int left_binding_power (const_TokenPtr token);
diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc
index dd9398b..da50948 100644
--- a/gcc/rust/rust-session-manager.cc
+++ b/gcc/rust/rust-session-manager.cc
@@ -344,8 +344,8 @@ Session::enable_dump (std::string arg)
if (arg == "all")
{
rust_error_at (Location (),
- "dumping all is not supported as of now. choose %<lex%>, "
- "%<parse%>, or %<target_options%>");
+ "dumping all is not supported as of now. choose %<lex%>, %<parse%>, "
+ "or %<target_options%>");
return false;
}
else if (arg == "lex")
@@ -390,8 +390,8 @@ Session::enable_dump (std::string arg)
else
{
rust_error_at (Location (),
- "dump option %qs was unrecognised. choose %<lex%>, "
- "%<parse%>, or %<target_options%>",
+ "dump option %qs was unrecognised. choose %<lex%>, %<parse%>, or "
+ "%<target_options%>",
arg.c_str ());
return false;
}
@@ -472,7 +472,6 @@ Session::parse_file (const char *filename)
if (options.dump_option == CompileOptions::REGISTER_PLUGINS_DUMP)
{
// TODO: what do I dump here?
- return;
}
// injection pipeline stage
@@ -482,7 +481,6 @@ Session::parse_file (const char *filename)
if (options.dump_option == CompileOptions::INJECTION_DUMP)
{
// TODO: what do I dump here? injected crate names?
- return;
}
// expansion pipeline stage
@@ -491,8 +489,10 @@ Session::parse_file (const char *filename)
if (options.dump_option == CompileOptions::EXPANSION_DUMP)
{
- // TODO: what do I dump here? expanded macros? AST with expanded macros?
- return;
+ // dump AST with expanded stuff
+ fprintf (stderr, "BEGIN POST-EXPANSION AST DUMP\n");
+ parser.debug_dump_ast_output (parsed_crate);
+ fprintf (stderr, "END POST-EXPANSION AST DUMP\n");
}
// resolution pipeline stage
@@ -502,7 +502,6 @@ Session::parse_file (const char *filename)
if (options.dump_option == CompileOptions::RESOLUTION_DUMP)
{
// TODO: what do I dump here? resolved names? AST with resolved names?
- return;
}
if (saw_errors ())
@@ -630,8 +629,8 @@ Session::injection (AST::Crate &crate)
* rustc also has a "quote" macro that is defined differently and is
* supposedly not stable so eh. */
/* TODO: actually implement injection of these macros. In particular, derive
- * macros, cfg, and
- * test should be prioritised since they seem to be used the most. */
+ * macros, cfg, and test should be prioritised since they seem to be used the
+ * most. */
// crate injection
std::vector<std::string> names;
@@ -719,7 +718,7 @@ Session::expansion (AST::Crate &crate)
// create extctxt? from parse session, cfg, and resolver?
/* expand by calling cxtctxt object's monotonic_expander's expand_crate
* method. */
- MacroExpander expander (crate, cfg);
+ MacroExpander expander (crate, cfg, *this);
expander.expand_crate ();
// error reporting - check unused macros, get missing fragment specifiers