+2011-11-29 Sanjoy Das <thedigitalangel@gmail.com>
+ Ian Lance Taylor <iant@google.com>
+
+ * go-location.h: New file.
+ * go-linemap.cc: New file.
+ * go-gcc.cc: Change all uses of source_location to Location.
+ * Make-lang.in (GO_OBJS): Add go/go-linemap.o.
+ (GO_LINEMAP_H): New variable.
+ (GO_LEX_H): Use $(GO_LINEMAP_H).
+ (GO_GOGO_H, GO_TYPES_H, GO_IMPORT_H): Likewise.
+ (go/go-linemap.o): New target.
+
2011-11-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* Make-lang.in (gospec.o): Pass SHLIB instead of SHLIB_LINK.
go/go-dump.o \
go/go-gcc.o \
go/go-lang.o \
+ go/go-linemap.o \
go/go-optimize.o \
go/go.o \
go/gogo-tree.o \
$(DIAGNOSTIC_CORE_H) $(INPUT_H) intl.h
GO_C_H = go/go-c.h $(MACHMODE_H)
-GO_LEX_H = go/gofrontend/lex.h go/gofrontend/operator.h
+GO_LINEMAP_H = go/gofrontend/go-linemap.h $(GO_SYSTEM_H) go/go-location.h
+GO_LEX_H = go/gofrontend/lex.h go/gofrontend/operator.h $(GO_LINEMAP_H)
GO_PARSE_H = go/gofrontend/parse.h
-GO_GOGO_H = go/gofrontend/gogo.h
-GO_TYPES_H = go/gofrontend/types.h
+GO_GOGO_H = go/gofrontend/gogo.h $(GO_LINEMAP_H)
+GO_TYPES_H = go/gofrontend/types.h $(GO_LINEMAP_H)
GO_STATEMENTS_H = go/gofrontend/statements.h go/gofrontend/operator.h
GO_EXPRESSIONS_H = go/gofrontend/expressions.h go/gofrontend/operator.h
GO_EXPORT_H = go/gofrontend/export.h go/gofrontend/string-dump.h
-GO_IMPORT_H = go/gofrontend/import.h $(GO_EXPORT_H)
+GO_IMPORT_H = go/gofrontend/import.h $(GO_EXPORT_H) $(GO_LINEMAP_H)
GO_RUNTIME_H = go/gofrontend/runtime.h go/gofrontend/runtime.def
GO_AST_DUMP_H = go/gofrontend/ast-dump.h go/gofrontend/string-dump.h
go/gofrontend/backend.h
$(CXX) -c $(GOINCLUDES) $(ALL_CPPFLAGS) $(ALL_CXXFLAGS) $< $(OUTPUT_OPTION)
+go/go-linemap.o: go/go-linemap.cc $(GO_SYSTEM_H) $(GO_LINEMAP_H)
+ $(CXX) -c $(GOINCLUDES) $(ALL_CPPFLAGS) $(ALL_CXXFLAGS) $< $(OUTPUT_OPTION)
+
go/%.o: go/gofrontend/%.cc
$(CXX) -c $(GOINCLUDES) $(ALL_CPPFLAGS) $(ALL_CXXFLAGS) $< $(OUTPUT_OPTION)
function_type(const Btyped_identifier&,
const std::vector<Btyped_identifier>&,
const std::vector<Btyped_identifier>&,
- source_location);
+ const Location);
Btype*
struct_type(const std::vector<Btyped_identifier>&);
array_type(Btype*, Bexpression*);
Btype*
- placeholder_pointer_type(const std::string&, source_location, bool);
+ placeholder_pointer_type(const std::string&, Location, bool);
bool
set_placeholder_pointer_type(Btype*, Btype*);
set_placeholder_function_type(Btype*, Btype*);
Btype*
- placeholder_struct_type(const std::string&, source_location);
+ placeholder_struct_type(const std::string&, Location);
bool
set_placeholder_struct_type(Btype* placeholder,
const std::vector<Btyped_identifier>&);
Btype*
- placeholder_array_type(const std::string&, source_location);
+ placeholder_array_type(const std::string&, Location);
bool
set_placeholder_array_type(Btype*, Btype*, Bexpression*);
Btype*
- named_type(const std::string&, Btype*, source_location);
+ named_type(const std::string&, Btype*, Location);
Btype*
circular_pointer_type(Btype*, bool);
init_statement(Bvariable* var, Bexpression* init);
Bstatement*
- assignment_statement(Bexpression* lhs, Bexpression* rhs, source_location);
+ assignment_statement(Bexpression* lhs, Bexpression* rhs, Location);
Bstatement*
return_statement(Bfunction*, const std::vector<Bexpression*>&,
- source_location);
+ Location);
Bstatement*
if_statement(Bexpression* condition, Bblock* then_block, Bblock* else_block,
- source_location);
+ Location);
Bstatement*
switch_statement(Bexpression* value,
const std::vector<std::vector<Bexpression*> >& cases,
const std::vector<Bstatement*>& statements,
- source_location);
+ Location);
Bstatement*
compound_statement(Bstatement*, Bstatement*);
Bblock*
block(Bfunction*, Bblock*, const std::vector<Bvariable*>&,
- source_location, source_location);
+ Location, Location);
void
block_add_statements(Bblock*, const std::vector<Bstatement*>&);
Btype* btype,
bool is_external,
bool is_hidden,
- source_location location);
+ Location location);
void
global_variable_set_init(Bvariable*, Bexpression*);
Bvariable*
local_variable(Bfunction*, const std::string&, Btype*, bool,
- source_location);
+ Location);
Bvariable*
parameter_variable(Bfunction*, const std::string&, Btype*, bool,
- source_location);
+ Location);
Bvariable*
temporary_variable(Bfunction*, Bblock*, Btype*, Bexpression*, bool,
- source_location, Bstatement**);
+ Location, Bstatement**);
Bvariable*
- immutable_struct(const std::string&, bool, Btype*, source_location);
+ immutable_struct(const std::string&, bool, Btype*, Location);
void
immutable_struct_set_init(Bvariable*, const std::string&, bool, Btype*,
- source_location, Bexpression*);
+ Location, Bexpression*);
Bvariable*
- immutable_struct_reference(const std::string&, Btype*, source_location);
+ immutable_struct_reference(const std::string&, Btype*, Location);
// Labels.
Blabel*
- label(Bfunction*, const std::string& name, source_location);
+ label(Bfunction*, const std::string& name, Location);
Bstatement*
label_definition_statement(Blabel*);
Bstatement*
- goto_statement(Blabel*, source_location);
+ goto_statement(Blabel*, Location);
Bexpression*
- label_address(Blabel*, source_location);
+ label_address(Blabel*, Location);
private:
// Make a Bexpression from a tree.
Gcc_backend::function_type(const Btyped_identifier& receiver,
const std::vector<Btyped_identifier>& parameters,
const std::vector<Btyped_identifier>& results,
- source_location location)
+ Location location)
{
tree args = NULL_TREE;
tree* pp = &args;
if (field_type_tree == error_mark_node)
return this->error_type();
gcc_assert(TYPE_SIZE(field_type_tree) != NULL_TREE);
- tree field = build_decl(location, FIELD_DECL, name_tree,
- field_type_tree);
+ tree field = build_decl(location.gcc_location(), FIELD_DECL,
+ name_tree, field_type_tree);
DECL_CONTEXT(field) = result;
*pp = field;
pp = &DECL_CHAIN(field);
tree type_tree = p->btype->get_tree();
if (type_tree == error_mark_node)
return this->error_type();
- tree field = build_decl(p->location, FIELD_DECL, name_tree, type_tree);
+ tree field = build_decl(p->location.gcc_location(), FIELD_DECL, name_tree,
+ type_tree);
DECL_CONTEXT(field) = fill_tree;
*pp = field;
pp = &DECL_CHAIN(field);
Btype*
Gcc_backend::placeholder_pointer_type(const std::string& name,
- source_location location, bool)
+ Location location, bool)
{
tree ret = build_variant_type_copy(ptr_type_node);
if (!name.empty())
{
- tree decl = build_decl(location, TYPE_DECL,
+ tree decl = build_decl(location.gcc_location(), TYPE_DECL,
get_identifier_from_string(name),
ret);
TYPE_NAME(ret) = decl;
Btype*
Gcc_backend::placeholder_struct_type(const std::string& name,
- source_location location)
+ Location location)
{
tree ret = make_node(RECORD_TYPE);
- tree decl = build_decl(location, TYPE_DECL,
+ tree decl = build_decl(location.gcc_location(), TYPE_DECL,
get_identifier_from_string(name),
ret);
TYPE_NAME(ret) = decl;
Btype*
Gcc_backend::placeholder_array_type(const std::string& name,
- source_location location)
+ Location location)
{
tree ret = make_node(ARRAY_TYPE);
- tree decl = build_decl(location, TYPE_DECL,
+ tree decl = build_decl(location.gcc_location(), TYPE_DECL,
get_identifier_from_string(name),
ret);
TYPE_NAME(ret) = decl;
Btype*
Gcc_backend::named_type(const std::string& name, Btype* btype,
- source_location location)
+ Location location)
{
tree type = btype->get_tree();
if (type == error_mark_node)
return this->error_type();
type = build_variant_type_copy(type);
- tree decl = build_decl(location, TYPE_DECL,
+ tree decl = build_decl(location.gcc_location(), TYPE_DECL,
get_identifier_from_string(name),
type);
TYPE_NAME(type) = decl;
Bstatement*
Gcc_backend::assignment_statement(Bexpression* lhs, Bexpression* rhs,
- source_location location)
+ Location location)
{
tree lhs_tree = lhs->get_tree();
tree rhs_tree = rhs->get_tree();
if (lhs_tree == error_mark_node || rhs_tree == error_mark_node)
return this->error_statement();
- return this->make_statement(fold_build2_loc(location, MODIFY_EXPR,
+ return this->make_statement(fold_build2_loc(location.gcc_location(),
+ MODIFY_EXPR,
void_type_node,
lhs_tree, rhs_tree));
}
Bstatement*
Gcc_backend::return_statement(Bfunction* bfunction,
const std::vector<Bexpression*>& vals,
- source_location location)
+ Location location)
{
tree fntree = bfunction->get_tree();
if (fntree == error_mark_node)
return this->error_statement();
tree ret;
if (vals.empty())
- ret = fold_build1_loc(location, RETURN_EXPR, void_type_node, NULL_TREE);
+ ret = fold_build1_loc(location.gcc_location(), RETURN_EXPR, void_type_node,
+ NULL_TREE);
else if (vals.size() == 1)
{
tree val = vals.front()->get_tree();
if (val == error_mark_node)
return this->error_statement();
- tree set = fold_build2_loc(location, MODIFY_EXPR, void_type_node,
- result, vals.front()->get_tree());
- ret = fold_build1_loc(location, RETURN_EXPR, void_type_node, set);
+ tree set = fold_build2_loc(location.gcc_location(), MODIFY_EXPR,
+ void_type_node, result,
+ vals.front()->get_tree());
+ ret = fold_build1_loc(location.gcc_location(), RETURN_EXPR,
+ void_type_node, set);
}
else
{
p++, field = DECL_CHAIN(field))
{
gcc_assert(field != NULL_TREE);
- tree ref = fold_build3_loc(location, COMPONENT_REF, TREE_TYPE(field),
- rettmp, field, NULL_TREE);
+ tree ref = fold_build3_loc(location.gcc_location(), COMPONENT_REF,
+ TREE_TYPE(field), rettmp, field,
+ NULL_TREE);
tree val = (*p)->get_tree();
if (val == error_mark_node)
return this->error_statement();
- tree set = fold_build2_loc(location, MODIFY_EXPR, void_type_node,
+ tree set = fold_build2_loc(location.gcc_location(), MODIFY_EXPR,
+ void_type_node,
ref, (*p)->get_tree());
append_to_statement_list(set, &stmt_list);
}
gcc_assert(field == NULL_TREE);
- tree set = fold_build2_loc(location, MODIFY_EXPR, void_type_node,
+ tree set = fold_build2_loc(location.gcc_location(), MODIFY_EXPR,
+ void_type_node,
result, rettmp);
- tree ret_expr = fold_build1_loc(location, RETURN_EXPR, void_type_node,
- set);
+ tree ret_expr = fold_build1_loc(location.gcc_location(), RETURN_EXPR,
+ void_type_node, set);
append_to_statement_list(ret_expr, &stmt_list);
ret = stmt_list;
}
Bstatement*
Gcc_backend::if_statement(Bexpression* condition, Bblock* then_block,
- Bblock* else_block, source_location location)
+ Bblock* else_block, Location location)
{
tree cond_tree = condition->get_tree();
tree then_tree = then_block->get_tree();
|| then_tree == error_mark_node
|| else_tree == error_mark_node)
return this->error_statement();
- tree ret = build3_loc(location, COND_EXPR, void_type_node, cond_tree,
- then_tree, else_tree);
+ tree ret = build3_loc(location.gcc_location(), COND_EXPR, void_type_node,
+ cond_tree, then_tree, else_tree);
return this->make_statement(ret);
}
Bexpression* value,
const std::vector<std::vector<Bexpression*> >& cases,
const std::vector<Bstatement*>& statements,
- source_location switch_location)
+ Location switch_location)
{
gcc_assert(cases.size() == statements.size());
if (pc->empty())
{
source_location loc = (*ps != NULL
- ? EXPR_LOCATION((*ps)->get_tree())
- : UNKNOWN_LOCATION);
+ ? EXPR_LOCATION((*ps)->get_tree())
+ : UNKNOWN_LOCATION);
tree label = create_artificial_label(loc);
tree c = build_case_label(NULL_TREE, NULL_TREE, label);
append_to_statement_list(c, &stmt_list);
tree tv = value->get_tree();
if (tv == error_mark_node)
return this->error_statement();
- tree t = build3_loc(switch_location, SWITCH_EXPR, void_type_node,
- tv, stmt_list, NULL_TREE);
+ tree t = build3_loc(switch_location.gcc_location(), SWITCH_EXPR,
+ void_type_node, tv, stmt_list, NULL_TREE);
return this->make_statement(t);
}
Bblock*
Gcc_backend::block(Bfunction* function, Bblock* enclosing,
const std::vector<Bvariable*>& vars,
- source_location start_location,
- source_location)
+ Location start_location,
+ Location)
{
tree block_tree = make_node(BLOCK);
if (enclosing == NULL)
TREE_USED(block_tree) = 1;
- tree bind_tree = build3_loc(start_location, BIND_EXPR, void_type_node,
- BLOCK_VARS(block_tree), NULL_TREE, block_tree);
+ tree bind_tree = build3_loc(start_location.gcc_location(), BIND_EXPR,
+ void_type_node, BLOCK_VARS(block_tree),
+ NULL_TREE, block_tree);
TREE_SIDE_EFFECTS(bind_tree) = 1;
return new Bblock(bind_tree);
Btype* btype,
bool is_external,
bool is_hidden,
- source_location location)
+ Location location)
{
tree type_tree = btype->get_tree();
if (type_tree == error_mark_node)
std::string var_name(package_name);
var_name.push_back('.');
var_name.append(name);
- tree decl = build_decl(location, VAR_DECL,
+ tree decl = build_decl(location.gcc_location(), VAR_DECL,
get_identifier_from_string(var_name),
type_tree);
if (is_external)
Bvariable*
Gcc_backend::local_variable(Bfunction* function, const std::string& name,
Btype* btype, bool is_address_taken,
- source_location location)
+ Location location)
{
tree type_tree = btype->get_tree();
if (type_tree == error_mark_node)
return this->error_variable();
- tree decl = build_decl(location, VAR_DECL,
+ tree decl = build_decl(location.gcc_location(), VAR_DECL,
get_identifier_from_string(name),
type_tree);
DECL_CONTEXT(decl) = function->get_tree();
Bvariable*
Gcc_backend::parameter_variable(Bfunction* function, const std::string& name,
Btype* btype, bool is_address_taken,
- source_location location)
+ Location location)
{
tree type_tree = btype->get_tree();
if (type_tree == error_mark_node)
return this->error_variable();
- tree decl = build_decl(location, PARM_DECL,
+ tree decl = build_decl(location.gcc_location(), PARM_DECL,
get_identifier_from_string(name),
type_tree);
DECL_CONTEXT(decl) = function->get_tree();
Gcc_backend::temporary_variable(Bfunction* function, Bblock* bblock,
Btype* btype, Bexpression* binit,
bool is_address_taken,
- source_location location,
+ Location location,
Bstatement** pstatement)
{
tree type_tree = btype->get_tree();
else
{
gcc_assert(bblock != NULL);
- var = build_decl(location, VAR_DECL,
+ var = build_decl(location.gcc_location(), VAR_DECL,
create_tmp_var_name("GOTMP"),
type_tree);
DECL_ARTIFICIAL(var) = 1;
}
if (init_tree != NULL_TREE)
- DECL_INITIAL(var) = fold_convert_loc(location, type_tree, init_tree);
+ DECL_INITIAL(var) = fold_convert_loc(location.gcc_location(), type_tree,
+ init_tree);
if (is_address_taken)
TREE_ADDRESSABLE(var) = 1;
- *pstatement = this->make_statement(build1_loc(location, DECL_EXPR,
+ *pstatement = this->make_statement(build1_loc(location.gcc_location(),
+ DECL_EXPR,
void_type_node, var));
return new Bvariable(var);
}
Bvariable*
Gcc_backend::immutable_struct(const std::string& name, bool, Btype* btype,
- source_location location)
+ Location location)
{
tree type_tree = btype->get_tree();
if (type_tree == error_mark_node)
return this->error_variable();
gcc_assert(TREE_CODE(type_tree) == RECORD_TYPE);
- tree decl = build_decl(location, VAR_DECL,
+ tree decl = build_decl(location.gcc_location(), VAR_DECL,
get_identifier_from_string(name),
build_qualified_type(type_tree, TYPE_QUAL_CONST));
TREE_STATIC(decl) = 1;
void
Gcc_backend::immutable_struct_set_init(Bvariable* var, const std::string&,
bool is_common, Btype*,
- source_location,
+ Location,
Bexpression* initializer)
{
tree decl = var->get_tree();
Bvariable*
Gcc_backend::immutable_struct_reference(const std::string& name, Btype* btype,
- source_location location)
+ Location location)
{
tree type_tree = btype->get_tree();
if (type_tree == error_mark_node)
return this->error_variable();
gcc_assert(TREE_CODE(type_tree) == RECORD_TYPE);
- tree decl = build_decl(location, VAR_DECL,
+ tree decl = build_decl(location.gcc_location(), VAR_DECL,
get_identifier_from_string(name),
build_qualified_type(type_tree, TYPE_QUAL_CONST));
TREE_READONLY(decl) = 1;
Blabel*
Gcc_backend::label(Bfunction* function, const std::string& name,
- source_location location)
+ Location location)
{
tree decl;
if (name.empty())
- decl = create_artificial_label(location);
+ decl = create_artificial_label(location.gcc_location());
else
{
tree id = get_identifier_from_string(name);
- decl = build_decl(location, LABEL_DECL, id, void_type_node);
+ decl = build_decl(location.gcc_location(), LABEL_DECL, id,
+ void_type_node);
DECL_CONTEXT(decl) = function->get_tree();
}
return new Blabel(decl);
// Make a goto statement.
Bstatement*
-Gcc_backend::goto_statement(Blabel* label, source_location location)
+Gcc_backend::goto_statement(Blabel* label, Location location)
{
tree lab = label->get_tree();
- tree ret = fold_build1_loc(location, GOTO_EXPR, void_type_node, lab);
+ tree ret = fold_build1_loc(location.gcc_location(), GOTO_EXPR, void_type_node,
+ lab);
return this->make_statement(ret);
}
// Get the address of a label.
Bexpression*
-Gcc_backend::label_address(Blabel* label, source_location location)
+Gcc_backend::label_address(Blabel* label, Location location)
{
tree lab = label->get_tree();
TREE_USED(lab) = 1;
TREE_ADDRESSABLE(lab) = 1;
- tree ret = fold_convert_loc(location, ptr_type_node,
- build_fold_addr_expr_loc(location, lab));
+ tree ret = fold_convert_loc(location.gcc_location(), ptr_type_node,
+ build_fold_addr_expr_loc(location.gcc_location(),
+ lab));
return this->make_expression(ret);
}
--- /dev/null
+// go-linemap.cc -- GCC implementation of Linemap.
+
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "go-linemap.h"
+
+// This class implements the Linemap interface defined by the
+// frontend.
+
+class Gcc_linemap : public Linemap
+{
+ public:
+ Gcc_linemap()
+ : Linemap(),
+ in_file_(false)
+ { }
+
+ void
+ start_file(const char* file_name, unsigned int line_begin);
+
+ void
+ start_line(unsigned int line_number, unsigned int line_size);
+
+ Location
+ get_location(unsigned int column);
+
+ void
+ stop();
+
+ protected:
+ Location
+ get_predeclared_location();
+
+ Location
+ get_unknown_location();
+
+ bool
+ is_predeclared(Location);
+
+ bool
+ is_unknown(Location);
+
+ private:
+ // Whether we are currently reading a file.
+ bool in_file_;
+};
+
+Linemap* Linemap::instance_ = NULL;
+
+// Start getting locations from a new file.
+
+void
+Gcc_linemap::start_file(const char *file_name, unsigned line_begin)
+{
+ if (this->in_file_)
+ linemap_add(line_table, LC_LEAVE, 0, NULL, 0);
+ linemap_add(line_table, LC_ENTER, 0, file_name, line_begin);
+ this->in_file_ = true;
+}
+
+// Stop getting locations.
+
+void
+Gcc_linemap::stop()
+{
+ linemap_add(line_table, LC_LEAVE, 0, NULL, 0);
+ this->in_file_ = false;
+}
+
+// Start a new line.
+
+void
+Gcc_linemap::start_line(unsigned lineno, unsigned linesize)
+{
+ linemap_line_start(line_table, lineno, linesize);
+}
+
+// Get a location.
+
+Location
+Gcc_linemap::get_location(unsigned column)
+{
+ return Location(linemap_position_for_column(line_table, column));
+}
+
+// Get the unknown location.
+
+Location
+Gcc_linemap::get_unknown_location()
+{
+ return Location(UNKNOWN_LOCATION);
+}
+
+// Get the predeclared location.
+
+Location
+Gcc_linemap::get_predeclared_location()
+{
+ return Location(BUILTINS_LOCATION);
+}
+
+// Return whether a location is the predeclared location.
+
+bool
+Gcc_linemap::is_predeclared(Location loc)
+{
+ return loc.gcc_location() == BUILTINS_LOCATION;
+}
+
+// Return whether a location is the unknown location.
+
+bool
+Gcc_linemap::is_unknown(Location loc)
+{
+ return loc.gcc_location() == UNKNOWN_LOCATION;
+}
+
+// Return the Linemap to use for the gcc backend.
+
+Linemap*
+go_get_linemap()
+{
+ return new Gcc_linemap;
+}
--- /dev/null
+// go-location.h -- GCC specific Location declaration. -*- C++ -*-
+
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#ifndef GO_LOCATION_H
+#define GO_LOCATION_H
+
+#include "go-system.h"
+
+// A location in an input source file.
+
+class Location
+{
+ public:
+ Location()
+ : gcc_loc_(UNKNOWN_LOCATION)
+ { }
+
+ explicit Location(source_location loc)
+ : gcc_loc_(loc)
+ { }
+
+ source_location
+ gcc_location() const
+ { return this->gcc_loc_; }
+
+ // Temporary hack till error_at and warning_at can deal with a Location.
+ operator source_location() const
+ { return this->gcc_loc_; }
+
+ private:
+ source_location gcc_loc_;
+};
+
+// The Go frontend requires the ability to compare Locations.
+
+inline bool
+operator<(Location loca, Location locb)
+{
+ return loca.gcc_location() < locb.gcc_location();
+}
+
+#endif // !defined(GO_LOCATION_H)
{
std::string name;
Btype* btype;
- source_location location;
+ Location location;
Btyped_identifier()
: name(), btype(NULL), location(UNKNOWN_LOCATION)
{ }
Btyped_identifier(const std::string& a_name, Btype* a_btype,
- source_location a_location)
+ Location a_location)
: name(a_name), btype(a_btype), location(a_location)
{ }
};
function_type(const Btyped_identifier& receiver,
const std::vector<Btyped_identifier>& parameters,
const std::vector<Btyped_identifier>& results,
- source_location location) = 0;
+ Location location) = 0;
// Get a struct type.
virtual Btype*
// parameter to set_placeholder_pointer_type or
// set_placeholder_function_type.
virtual Btype*
- placeholder_pointer_type(const std::string& name, source_location,
+ placeholder_pointer_type(const std::string& name, Location,
bool for_function) = 0;
// Fill in a placeholder pointer type as a pointer. This takes a
// Create a placeholder struct type. This is used for a named
// struct type, as with placeholder_pointer_type.
virtual Btype*
- placeholder_struct_type(const std::string& name, source_location) = 0;
+ placeholder_struct_type(const std::string& name, Location) = 0;
// Fill in a placeholder struct type. This takes a type returned by
// placeholder_struct_type and arranges for it to become a real
// type, as with placeholder_pointer_type, to handle cases like
// type A []*A.
virtual Btype*
- placeholder_array_type(const std::string& name, source_location) = 0;
+ placeholder_array_type(const std::string& name, Location) = 0;
// Fill in a placeholder array type. This takes a type returned by
// placeholder_array_type and arranges for it to become a real array
// placeholder_array_type.. (It may be called for a pointer,
// struct, or array type in a case like "type P *byte; type Q P".)
virtual Btype*
- named_type(const std::string& name, Btype*, source_location) = 0;
+ named_type(const std::string& name, Btype*, Location) = 0;
// Create a marker for a circular pointer type. Go pointer and
// function types can refer to themselves in ways that are not
// Create an assignment statement.
virtual Bstatement*
assignment_statement(Bexpression* lhs, Bexpression* rhs,
- source_location) = 0;
+ Location) = 0;
// Create a return statement, passing the representation of the
// function and the list of values to return.
virtual Bstatement*
return_statement(Bfunction*, const std::vector<Bexpression*>&,
- source_location) = 0;
+ Location) = 0;
// Create an if statement. ELSE_BLOCK may be NULL.
virtual Bstatement*
if_statement(Bexpression* condition, Bblock* then_block, Bblock* else_block,
- source_location) = 0;
+ Location) = 0;
// Create a switch statement where the case values are constants.
// CASES and STATEMENTS must have the same number of entries. If
switch_statement(Bexpression* value,
const std::vector<std::vector<Bexpression*> >& cases,
const std::vector<Bstatement*>& statements,
- source_location) = 0;
+ Location) = 0;
// Create a single statement from two statements.
virtual Bstatement*
virtual Bblock*
block(Bfunction* function, Bblock* enclosing,
const std::vector<Bvariable*>& vars,
- source_location start_location, source_location end_location) = 0;
+ Location start_location, Location end_location) = 0;
// Add the statements to a block. The block is created first. Then
// the statements are created. Then the statements are added to the
Btype* btype,
bool is_external,
bool is_hidden,
- source_location location) = 0;
+ Location location) = 0;
// A global variable will 1) be initialized to zero, or 2) be
// initialized to a constant value, or 3) be initialized in the init
// init_statement to set the initial value.
virtual Bvariable*
local_variable(Bfunction* function, const std::string& name, Btype* type,
- bool is_address_taken, source_location location) = 0;
+ bool is_address_taken, Location location) = 0;
// Create a function parameter. This is an incoming parameter, not
// a result parameter (result parameters are treated as local
virtual Bvariable*
parameter_variable(Bfunction* function, const std::string& name,
Btype* type, bool is_address_taken,
- source_location location) = 0;
+ Location location) = 0;
// Create a temporary variable. A temporary variable has no name,
// just a type. We pass in FUNCTION and BLOCK in case they are
// *PSTATEMENT to a statement which initializes the variable.
virtual Bvariable*
temporary_variable(Bfunction*, Bblock*, Btype*, Bexpression* init,
- bool address_is_taken, source_location location,
+ bool address_is_taken, Location location,
Bstatement** pstatement) = 0;
// Create a named immutable initialized data structure. This is
// set_immutable_struct_initializer.
virtual Bvariable*
immutable_struct(const std::string& name, bool is_common, Btype* type,
- source_location) = 0;
+ Location) = 0;
// Set the initial value of a variable created by immutable_struct.
// The NAME, IS_COMMON, TYPE, and location parameters are the same
// immutable_struct.
virtual void
immutable_struct_set_init(Bvariable*, const std::string& name,
- bool is_common, Btype* type, source_location,
+ bool is_common, Btype* type, Location,
Bexpression* initializer) = 0;
// Create a reference to a named immutable initialized data
// corresponds to an extern const global variable in C.
virtual Bvariable*
immutable_struct_reference(const std::string& name, Btype* type,
- source_location) = 0;
+ Location) = 0;
// Labels.
// created by the frontend for a loop construct. The location is
// where the the label is defined.
virtual Blabel*
- label(Bfunction*, const std::string& name, source_location) = 0;
+ label(Bfunction*, const std::string& name, Location) = 0;
// Create a statement which defines a label. This statement will be
// put into the codestream at the point where the label should be
// Create a goto statement to a label.
virtual Bstatement*
- goto_statement(Blabel*, source_location) = 0;
+ goto_statement(Blabel*, Location) = 0;
// Create an expression for the address of a label. This is used to
// get the return address of a deferred function which may call
// recover.
virtual Bexpression*
- label_address(Blabel*, source_location) = 0;
+ label_address(Blabel*, Location) = 0;
};
// The backend interface has to define this function.
return false;
// We can have two different variables with the same name.
- source_location loc1 = no1->location();
- source_location loc2 = no2->location();
+ Location loc1 = no1->location();
+ Location loc2 = no2->location();
if (loc1 < loc2)
return false;
if (loc1 > loc2)
if (named_type != NULL)
{
// The builtin types should have been predefined.
- go_assert(named_type->location() != BUILTINS_LOCATION
+ go_assert(!Linemap::is_predeclared_location(named_type->location())
|| (named_type->named_object()->package()->name()
== "unsafe"));
named_object = named_type->named_object();
// Class Expression.
Expression::Expression(Expression_classification classification,
- source_location location)
+ Location location)
: classification_(classification), location_(location)
{
}
tree
Expression::convert_for_assignment(Translate_context* context, Type* lhs_type,
Type* rhs_type, tree rhs_tree,
- source_location location)
+ Location location)
{
if (lhs_type == rhs_type)
return rhs_tree;
|| INTEGRAL_TYPE_P(lhs_type_tree)
|| SCALAR_FLOAT_TYPE_P(lhs_type_tree)
|| COMPLEX_FLOAT_TYPE_P(lhs_type_tree))
- return fold_convert_loc(location, lhs_type_tree, rhs_tree);
+ return fold_convert_loc(location.gcc_location(), lhs_type_tree, rhs_tree);
else if (TREE_CODE(lhs_type_tree) == RECORD_TYPE
&& TREE_CODE(TREE_TYPE(rhs_tree)) == RECORD_TYPE)
{
// gotten here.
go_assert(int_size_in_bytes(lhs_type_tree)
== int_size_in_bytes(TREE_TYPE(rhs_tree)));
- return fold_build1_loc(location, VIEW_CONVERT_EXPR, lhs_type_tree,
- rhs_tree);
+ return fold_build1_loc(location.gcc_location(), VIEW_CONVERT_EXPR,
+ lhs_type_tree, rhs_tree);
}
else
{
tree
Expression::convert_type_to_interface(Translate_context* context,
Type* lhs_type, Type* rhs_type,
- tree rhs_tree, source_location location)
+ tree rhs_tree, Location location)
{
Gogo* gogo = context->gogo();
Interface_type* lhs_interface_type = lhs_type->interface_type();
method_table =
rhs_named_type->interface_method_table(gogo, lhs_interface_type,
is_pointer);
- first_field_value = fold_convert_loc(location, const_ptr_type_node,
- method_table);
+ first_field_value = fold_convert_loc(location.gcc_location(),
+ const_ptr_type_node, method_table);
}
if (first_field_value == error_mark_node)
return error_mark_node;
go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
(lhs_is_empty ? "__type_descriptor" : "__methods")) == 0);
elt->index = field;
- elt->value = fold_convert_loc(location, TREE_TYPE(field), first_field_value);
+ elt->value = fold_convert_loc(location.gcc_location(), TREE_TYPE(field),
+ first_field_value);
elt = VEC_quick_push(constructor_elt, init, NULL);
field = DECL_CHAIN(field);
tree object_size = TYPE_SIZE_UNIT(TREE_TYPE(rhs_tree));
tree space = gogo->allocate_memory(rhs_type, object_size, location);
- space = fold_convert_loc(location, build_pointer_type(TREE_TYPE(rhs_tree)),
- space);
+ space = fold_convert_loc(location.gcc_location(),
+ build_pointer_type(TREE_TYPE(rhs_tree)), space);
space = save_expr(space);
- tree ref = build_fold_indirect_ref_loc(location, space);
+ tree ref = build_fold_indirect_ref_loc(location.gcc_location(), space);
TREE_THIS_NOTRAP(ref) = 1;
- tree set = fold_build2_loc(location, MODIFY_EXPR, void_type_node,
- ref, rhs_tree);
+ tree set = fold_build2_loc(location.gcc_location(), MODIFY_EXPR,
+ void_type_node, ref, rhs_tree);
- elt->value = fold_convert_loc(location, TREE_TYPE(field), space);
+ elt->value = fold_convert_loc(location.gcc_location(), TREE_TYPE(field),
+ space);
return build2(COMPOUND_EXPR, lhs_type_tree, set,
build_constructor(lhs_type_tree, init));
tree
Expression::get_interface_type_descriptor(Translate_context*,
Type* rhs_type, tree rhs_tree,
- source_location location)
+ Location location)
{
tree rhs_type_tree = TREE_TYPE(rhs_tree);
go_assert(TREE_CODE(rhs_type_tree) == RECORD_TYPE);
== 0);
go_assert(POINTER_TYPE_P(TREE_TYPE(v)));
v = save_expr(v);
- tree v1 = build_fold_indirect_ref_loc(location, v);
+ tree v1 = build_fold_indirect_ref_loc(location.gcc_location(), v);
go_assert(TREE_CODE(TREE_TYPE(v1)) == RECORD_TYPE);
tree f = TYPE_FIELDS(TREE_TYPE(v1));
go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(f)), "__type_descriptor")
== 0);
v1 = build3(COMPONENT_REF, TREE_TYPE(f), v1, f, NULL_TREE);
- tree eq = fold_build2_loc(location, EQ_EXPR, boolean_type_node, v,
- fold_convert_loc(location, TREE_TYPE(v),
- null_pointer_node));
- tree n = fold_convert_loc(location, TREE_TYPE(v1), null_pointer_node);
- return fold_build3_loc(location, COND_EXPR, TREE_TYPE(v1),
+ tree eq = fold_build2_loc(location.gcc_location(), EQ_EXPR, boolean_type_node,
+ v, fold_convert_loc(location.gcc_location(),
+ TREE_TYPE(v),
+ null_pointer_node));
+ tree n = fold_convert_loc(location.gcc_location(), TREE_TYPE(v1),
+ null_pointer_node);
+ return fold_build3_loc(location.gcc_location(), COND_EXPR, TREE_TYPE(v1),
eq, n, v1);
}
Expression::convert_interface_to_interface(Translate_context* context,
Type *lhs_type, Type *rhs_type,
tree rhs_tree, bool for_type_guard,
- source_location location)
+ Location location)
{
Gogo* gogo = context->gogo();
Interface_type* lhs_interface_type = lhs_type->interface_type();
return error_mark_node;
// This will panic if the interface conversion fails.
TREE_NOTHROW(assert_interface_decl) = 0;
- elt->value = fold_convert_loc(location, TREE_TYPE(field), call);
+ elt->value = fold_convert_loc(location.gcc_location(), TREE_TYPE(field),
+ call);
}
else if (lhs_is_empty)
{
return error_mark_node;
// This will panic if the interface conversion fails.
TREE_NOTHROW(convert_interface_decl) = 0;
- elt->value = fold_convert_loc(location, TREE_TYPE(field), call);
+ elt->value = fold_convert_loc(location.gcc_location(), TREE_TYPE(field),
+ call);
}
// The second field is simply the object pointer.
tree
Expression::convert_interface_to_type(Translate_context* context,
Type *lhs_type, Type* rhs_type,
- tree rhs_tree, source_location location)
+ tree rhs_tree, Location location)
{
Gogo* gogo = context->gogo();
tree rhs_type_tree = TREE_TYPE(rhs_tree);
// Otherwise it points to the value.
if (lhs_type->points_to() == NULL)
{
- val = fold_convert_loc(location, build_pointer_type(lhs_type_tree), val);
- val = build_fold_indirect_ref_loc(location, val);
+ val = fold_convert_loc(location.gcc_location(),
+ build_pointer_type(lhs_type_tree), val);
+ val = build_fold_indirect_ref_loc(location.gcc_location(), val);
}
return build2(COMPOUND_EXPR, lhs_type_tree, call,
- fold_convert_loc(location, lhs_type_tree, val));
+ fold_convert_loc(location.gcc_location(), lhs_type_tree, val));
}
// Convert an expression to a tree. This is implemented by the child
tree
Expression::check_bounds(tree val, tree bound_type, tree sofar,
- source_location loc)
+ Location loc)
{
tree val_type = TREE_TYPE(val);
tree ret = NULL_TREE;
if (!TYPE_UNSIGNED(val_type))
{
- ret = fold_build2_loc(loc, LT_EXPR, boolean_type_node, val,
+ ret = fold_build2_loc(loc.gcc_location(), LT_EXPR, boolean_type_node, val,
build_int_cst(val_type, 0));
if (ret == boolean_false_node)
ret = NULL_TREE;
&& !TYPE_UNSIGNED(bound_type)))
{
tree max = TYPE_MAX_VALUE(bound_type);
- tree big = fold_build2_loc(loc, GT_EXPR, boolean_type_node, val,
- fold_convert_loc(loc, val_type, max));
+ tree big = fold_build2_loc(loc.gcc_location(), GT_EXPR, boolean_type_node,
+ val, fold_convert_loc(loc.gcc_location(),
+ val_type, max));
if (big == boolean_false_node)
;
else if (ret == NULL_TREE)
ret = big;
else
- ret = fold_build2_loc(loc, TRUTH_OR_EXPR, boolean_type_node,
- ret, big);
+ ret = fold_build2_loc(loc.gcc_location(), TRUTH_OR_EXPR,
+ boolean_type_node, ret, big);
}
if (ret == NULL_TREE)
else if (sofar == NULL_TREE)
return ret;
else
- return fold_build2_loc(loc, TRUTH_OR_EXPR, boolean_type_node,
+ return fold_build2_loc(loc.gcc_location(), TRUTH_OR_EXPR, boolean_type_node,
sofar, ret);
}
class Error_expression : public Expression
{
public:
- Error_expression(source_location location)
+ Error_expression(Location location)
: Expression(EXPRESSION_ERROR, location)
{ }
}
Expression*
-Expression::make_error(source_location location)
+Expression::make_error(Location location)
{
return new Error_expression(location);
}
Type_expression : public Expression
{
public:
- Type_expression(Type* type, source_location location)
+ Type_expression(Type* type, Location location)
: Expression(EXPRESSION_TYPE, location),
type_(type)
{ }
}
Expression*
-Expression::make_type(Type* type, source_location location)
+Expression::make_type(Type* type, Location location)
{
return new Type_expression(type, location);
}
go_unreachable();
if (is_in_heap)
{
- ret = build_fold_indirect_ref_loc(this->location(), ret);
+ ret = build_fold_indirect_ref_loc(this->location().gcc_location(), ret);
TREE_THIS_NOTRAP(ret) = 1;
}
return ret;
// Make a reference to a variable in an expression.
Expression*
-Expression::make_var_reference(Named_object* var, source_location location)
+Expression::make_var_reference(Named_object* var, Location location)
{
if (var->is_sink())
return Expression::make_sink(location);
{
Btype* type_btype = this->type()->base()->get_backend(context->gogo());
tree type_tree = type_to_tree(type_btype);
- ret = fold_convert_loc(this->location(), type_tree, ret);
+ ret = fold_convert_loc(this->location().gcc_location(), type_tree, ret);
}
return ret;
}
Temporary_reference_expression*
Expression::make_temporary_reference(Temporary_statement* statement,
- source_location location)
+ Location location)
{
return new Temporary_reference_expression(statement, location);
}
class Sink_expression : public Expression
{
public:
- Sink_expression(source_location location)
+ Sink_expression(Location location)
: Expression(EXPRESSION_SINK, location),
type_(NULL), var_(NULL_TREE)
{ }
// Make a sink expression.
Expression*
-Expression::make_sink(source_location location)
+Expression::make_sink(Location location)
{
return new Sink_expression(location);
}
if (fndecl == error_mark_node)
return error_mark_node;
- return build_fold_addr_expr_loc(this->location(), fndecl);
+ return build_fold_addr_expr_loc(this->location().gcc_location(), fndecl);
}
// Get the tree for a function expression. This is used when we take
Expression*
Expression::make_func_reference(Named_object* function, Expression* closure,
- source_location location)
+ Location location)
{
return new Func_expression(function, closure, location);
}
Expression*
Unknown_expression::do_lower(Gogo*, Named_object*, Statement_inserter*, int)
{
- source_location location = this->location();
+ Location location = this->location();
Named_object* no = this->named_object_;
Named_object* real;
if (!no->is_unknown())
// Make a reference to an unknown name.
Expression*
-Expression::make_unknown_reference(Named_object* no, source_location location)
+Expression::make_unknown_reference(Named_object* no, Location location)
{
return new Unknown_expression(no, location);
}
class Boolean_expression : public Expression
{
public:
- Boolean_expression(bool val, source_location location)
+ Boolean_expression(bool val, Location location)
: Expression(EXPRESSION_BOOLEAN, location),
val_(val), type_(NULL)
{ }
// Make a boolean expression.
Expression*
-Expression::make_boolean(bool val, source_location location)
+Expression::make_boolean(bool val, Location location)
{
return new Boolean_expression(val, location);
}
// Make a string expression.
Expression*
-Expression::make_string(const std::string& val, source_location location)
+Expression::make_string(const std::string& val, Location location)
{
return new String_expression(val, location);
}
class Integer_expression : public Expression
{
public:
- Integer_expression(const mpz_t* val, Type* type, source_location location)
+ Integer_expression(const mpz_t* val, Type* type, Location location)
: Expression(EXPRESSION_INTEGER, location),
type_(type)
{ mpz_init_set(this->val_, *val); }
// Return whether VAL fits in the type.
static bool
- check_constant(mpz_t val, Type*, source_location);
+ check_constant(mpz_t val, Type*, Location);
// Write VAL to string dump.
static void
bool
Integer_expression::check_constant(mpz_t val, Type* type,
- source_location location)
+ Location location)
{
if (type == NULL)
return true;
Expression*
Expression::make_integer(const mpz_t* val, Type* type,
- source_location location)
+ Location location)
{
return new Integer_expression(val, type, location);
}
class Float_expression : public Expression
{
public:
- Float_expression(const mpfr_t* val, Type* type, source_location location)
+ Float_expression(const mpfr_t* val, Type* type, Location location)
: Expression(EXPRESSION_FLOAT, location),
type_(type)
{
// Return whether VAL fits in the type.
static bool
- check_constant(mpfr_t val, Type*, source_location);
+ check_constant(mpfr_t val, Type*, Location);
// Write VAL to export data.
static void
bool
Float_expression::check_constant(mpfr_t val, Type* type,
- source_location location)
+ Location location)
{
if (type == NULL)
return true;
// Make a float expression.
Expression*
-Expression::make_float(const mpfr_t* val, Type* type, source_location location)
+Expression::make_float(const mpfr_t* val, Type* type, Location location)
{
return new Float_expression(val, type, location);
}
{
public:
Complex_expression(const mpfr_t* real, const mpfr_t* imag, Type* type,
- source_location location)
+ Location location)
: Expression(EXPRESSION_COMPLEX, location),
type_(type)
{
// Return whether REAL/IMAG fits in the type.
static bool
- check_constant(mpfr_t real, mpfr_t imag, Type*, source_location);
+ check_constant(mpfr_t real, mpfr_t imag, Type*, Location);
// Write REAL/IMAG to string dump.
static void
bool
Complex_expression::check_constant(mpfr_t real, mpfr_t imag, Type* type,
- source_location location)
+ Location location)
{
if (type == NULL)
return true;
Expression*
Expression::make_complex(const mpfr_t* real, const mpfr_t* imag, Type* type,
- source_location location)
+ Location location)
{
return new Complex_expression(real, imag, type, location);
}
class Const_expression : public Expression
{
public:
- Const_expression(Named_object* constant, source_location location)
+ Const_expression(Named_object* constant, Location location)
: Expression(EXPRESSION_CONST_REFERENCE, location),
constant_(constant), type_(NULL), seen_(false)
{ }
Expression*
Expression::make_const_reference(Named_object* constant,
- source_location location)
+ Location location)
{
return new Const_expression(constant, location);
}
class Nil_expression : public Expression
{
public:
- Nil_expression(source_location location)
+ Nil_expression(Location location)
: Expression(EXPRESSION_NIL, location)
{ }
// Make a nil expression.
Expression*
-Expression::make_nil(source_location location)
+Expression::make_nil(Location location)
{
return new Nil_expression(location);
}
class Iota_expression : public Parser_expression
{
public:
- Iota_expression(source_location location)
+ Iota_expression(Location location)
: Parser_expression(EXPRESSION_IOTA, location)
{ }
Expression*
Expression::make_iota()
{
- static Iota_expression iota_expression(UNKNOWN_LOCATION);
+ static Iota_expression iota_expression(Linemap::unknown_location());
return &iota_expression;
}
{
public:
Type_conversion_expression(Type* type, Expression* expr,
- source_location location)
+ Location location)
: Expression(EXPRESSION_CONVERSION, location),
type_(type), expr_(expr), may_convert_function_types_(false)
{ }
{
Type* type = this->type_;
Expression* val = this->expr_;
- source_location location = this->location();
+ Location location = this->location();
if (type->integer_type() != NULL)
{
tree valptr = fold_convert(const_ptr_type_node,
a->value_pointer_tree(gogo, expr_tree));
tree len = a->length_tree(gogo, expr_tree);
- len = fold_convert_loc(this->location(), integer_type_node, len);
+ len = fold_convert_loc(this->location().gcc_location(), integer_type_node,
+ len);
if (e->integer_type()->is_unsigned()
&& e->integer_type()->bits() == 8)
{
else if (this->may_convert_function_types_
&& type->function_type() != NULL
&& expr_type->function_type() != NULL)
- ret = fold_convert_loc(this->location(), type_tree, expr_tree);
+ ret = fold_convert_loc(this->location().gcc_location(), type_tree,
+ expr_tree);
else
ret = Expression::convert_for_assignment(context, type, expr_type,
expr_tree, this->location());
// Make a type cast expression.
Expression*
-Expression::make_cast(Type* type, Expression* val, source_location location)
+Expression::make_cast(Type* type, Expression* val, Location location)
{
if (type->is_error_type() || val->is_error_expression())
return Expression::make_error(location);
{
public:
Unsafe_type_conversion_expression(Type* type, Expression* expr,
- source_location location)
+ Location location)
: Expression(EXPRESSION_UNSAFE_CONVERSION, location),
type_(type), expr_(expr)
{ }
if (type_tree == error_mark_node || expr_tree == error_mark_node)
return error_mark_node;
- source_location loc = this->location();
+ Location loc = this->location();
bool use_view_convert = false;
if (t->is_slice_type())
go_unreachable();
if (use_view_convert)
- return fold_build1_loc(loc, VIEW_CONVERT_EXPR, type_tree, expr_tree);
+ return fold_build1_loc(loc.gcc_location(), VIEW_CONVERT_EXPR, type_tree,
+ expr_tree);
else
- return fold_convert_loc(loc, type_tree, expr_tree);
+ return fold_convert_loc(loc.gcc_location(), type_tree, expr_tree);
}
// Dump ast representation for an unsafe type conversion expression.
Expression*
Expression::make_unsafe_cast(Type* type, Expression* expr,
- source_location location)
+ Location location)
{
return new Unsafe_type_conversion_expression(type, expr, location);
}
class Unary_expression : public Expression
{
public:
- Unary_expression(Operator op, Expression* expr, source_location location)
+ Unary_expression(Operator op, Expression* expr, Location location)
: Expression(EXPRESSION_UNARY, location),
op_(op), escapes_(true), create_temp_(false), expr_(expr)
{ }
// could be done, false if not.
static bool
eval_integer(Operator op, Type* utype, mpz_t uval, mpz_t val,
- source_location);
+ Location);
// Apply unary opcode OP to UVAL, setting VAL. Return true if this
// could be done, false if not.
Expression*
Unary_expression::do_lower(Gogo*, Named_object*, Statement_inserter*, int)
{
- source_location loc = this->location();
+ Location loc = this->location();
Operator op = this->op_;
Expression* expr = this->expr_;
bool
Unary_expression::eval_integer(Operator op, Type* utype, mpz_t uval, mpz_t val,
- source_location location)
+ Location location)
{
switch (op)
{
if (expr == error_mark_node)
return error_mark_node;
- source_location loc = this->location();
+ Location loc = this->location();
switch (this->op_)
{
case OPERATOR_PLUS:
tree compute_type = excess_precision_type(type);
if (compute_type != NULL_TREE)
expr = ::convert(compute_type, expr);
- tree ret = fold_build1_loc(loc, NEGATE_EXPR,
+ tree ret = fold_build1_loc(loc.gcc_location(), NEGATE_EXPR,
(compute_type != NULL_TREE
? compute_type
: type),
case OPERATOR_NOT:
if (TREE_CODE(TREE_TYPE(expr)) == BOOLEAN_TYPE)
- return fold_build1_loc(loc, TRUTH_NOT_EXPR, TREE_TYPE(expr), expr);
+ return fold_build1_loc(loc.gcc_location(), TRUTH_NOT_EXPR,
+ TREE_TYPE(expr), expr);
else
- return fold_build2_loc(loc, NE_EXPR, boolean_type_node, expr,
- build_int_cst(TREE_TYPE(expr), 0));
+ return fold_build2_loc(loc.gcc_location(), NE_EXPR, boolean_type_node,
+ expr, build_int_cst(TREE_TYPE(expr), 0));
case OPERATOR_XOR:
- return fold_build1_loc(loc, BIT_NOT_EXPR, TREE_TYPE(expr), expr);
+ return fold_build1_loc(loc.gcc_location(), BIT_NOT_EXPR, TREE_TYPE(expr),
+ expr);
case OPERATOR_AND:
if (!this->create_temp_)
// Build a decl for a constant constructor.
if (TREE_CODE(expr) == CONSTRUCTOR && TREE_CONSTANT(expr))
{
- tree decl = build_decl(this->location(), VAR_DECL,
+ tree decl = build_decl(this->location().gcc_location(), VAR_DECL,
create_tmp_var_name("C"), TREE_TYPE(expr));
DECL_EXTERNAL(decl) = 0;
TREE_PUBLIC(decl) = 0;
DECL_IGNORED_P(tmp) = 1;
DECL_INITIAL(tmp) = expr;
TREE_ADDRESSABLE(tmp) = 1;
- return build2_loc(loc, COMPOUND_EXPR,
+ return build2_loc(loc.gcc_location(), COMPOUND_EXPR,
build_pointer_type(TREE_TYPE(expr)),
- build1_loc(loc, DECL_EXPR, void_type_node, tmp),
- build_fold_addr_expr_loc(loc, tmp));
+ build1_loc(loc.gcc_location(), DECL_EXPR,
+ void_type_node, tmp),
+ build_fold_addr_expr_loc(loc.gcc_location(), tmp));
}
- return build_fold_addr_expr_loc(loc, expr);
+ return build_fold_addr_expr_loc(loc.gcc_location(), expr);
case OPERATOR_MULT:
{
{
if (!DECL_P(expr))
expr = save_expr(expr);
- tree compare = fold_build2_loc(loc, EQ_EXPR, boolean_type_node,
+ tree compare = fold_build2_loc(loc.gcc_location(), EQ_EXPR,
+ boolean_type_node,
expr,
fold_convert(TREE_TYPE(expr),
null_pointer_node));
tree crash = Gogo::runtime_error(RUNTIME_ERROR_NIL_DEREFERENCE,
loc);
- expr = fold_build2_loc(loc, COMPOUND_EXPR, TREE_TYPE(expr),
- build3(COND_EXPR, void_type_node,
- compare, crash, NULL_TREE),
+ expr = fold_build2_loc(loc.gcc_location(), COMPOUND_EXPR,
+ TREE_TYPE(expr), build3(COND_EXPR,
+ void_type_node,
+ compare, crash,
+ NULL_TREE),
expr);
}
{
Type* pt = this->expr_->type()->points_to();
tree ind = type_to_tree(pt->get_backend(context->gogo()));
- expr = fold_convert_loc(loc, build_pointer_type(ind), expr);
+ expr = fold_convert_loc(loc.gcc_location(),
+ build_pointer_type(ind), expr);
}
- return build_fold_indirect_ref_loc(loc, expr);
+ return build_fold_indirect_ref_loc(loc.gcc_location(), expr);
}
default:
// Make a unary expression.
Expression*
-Expression::make_unary(Operator op, Expression* expr, source_location location)
+Expression::make_unary(Operator op, Expression* expr, Location location)
{
return new Unary_expression(op, expr, location);
}
bool
Binary_expression::eval_integer(Operator op, Type* left_type, mpz_t left_val,
Type* right_type, mpz_t right_val,
- source_location location, mpz_t val)
+ Location location, mpz_t val)
{
bool is_shift_op = false;
switch (op)
bool
Binary_expression::eval_float(Operator op, Type* left_type, mpfr_t left_val,
Type* right_type, mpfr_t right_val,
- mpfr_t val, source_location location)
+ mpfr_t val, Location location)
{
switch (op)
{
Type *right_type,
mpfr_t right_real, mpfr_t right_imag,
mpfr_t real, mpfr_t imag,
- source_location location)
+ Location location)
{
switch (op)
{
Expression*
Binary_expression::do_lower(Gogo*, Named_object*, Statement_inserter*, int)
{
- source_location location = this->location();
+ Location location = this->location();
Operator op = this->op_;
Expression* left = this->left_;
Expression* right = this->right_;
bool
Binary_expression::check_operator_type(Operator op, Type* type,
- source_location location)
+ Location location)
{
switch (op)
{
{
this->report_error(_("negative shift count"));
mpz_set_ui(val, 0);
- source_location rloc = this->right_->location();
+ Location rloc = this->right_->location();
this->right_ = Expression::make_integer(&val, right_type,
rloc);
}
if (eval_saved == NULL_TREE)
eval_saved = right;
else
- eval_saved = fold_build2_loc(this->location(), COMPOUND_EXPR,
+ eval_saved = fold_build2_loc(this->location().gcc_location(),
+ COMPOUND_EXPR,
void_type_node, eval_saved, right);
}
}
- tree ret = fold_build2_loc(this->location(),
+ tree ret = fold_build2_loc(this->location().gcc_location(),
code,
compute_type != NULL_TREE ? compute_type : type,
left, right);
tree compare = fold_build2(LT_EXPR, boolean_type_node, right,
build_int_cst_type(TREE_TYPE(right), bits));
- tree overflow_result = fold_convert_loc(this->location(),
+ tree overflow_result = fold_convert_loc(this->location().gcc_location(),
TREE_TYPE(left),
integer_zero_node);
if (this->op_ == OPERATOR_RSHIFT
&& !this->left_->type()->integer_type()->is_unsigned())
{
- tree neg = fold_build2_loc(this->location(), LT_EXPR,
- boolean_type_node, left,
- fold_convert_loc(this->location(),
- TREE_TYPE(left),
- integer_zero_node));
- tree neg_one = fold_build2_loc(this->location(),
- MINUS_EXPR, TREE_TYPE(left),
- fold_convert_loc(this->location(),
- TREE_TYPE(left),
- integer_zero_node),
- fold_convert_loc(this->location(),
- TREE_TYPE(left),
- integer_one_node));
- overflow_result = fold_build3_loc(this->location(), COND_EXPR,
- TREE_TYPE(left), neg, neg_one,
- overflow_result);
- }
-
- ret = fold_build3_loc(this->location(), COND_EXPR, TREE_TYPE(left),
- compare, ret, overflow_result);
+ tree neg =
+ fold_build2_loc(this->location().gcc_location(), LT_EXPR,
+ boolean_type_node, left,
+ fold_convert_loc(this->location().gcc_location(),
+ TREE_TYPE(left),
+ integer_zero_node));
+ tree neg_one =
+ fold_build2_loc(this->location().gcc_location(),
+ MINUS_EXPR, TREE_TYPE(left),
+ fold_convert_loc(this->location().gcc_location(),
+ TREE_TYPE(left),
+ integer_zero_node),
+ fold_convert_loc(this->location().gcc_location(),
+ TREE_TYPE(left),
+ integer_one_node));
+ overflow_result =
+ fold_build3_loc(this->location().gcc_location(), COND_EXPR,
+ TREE_TYPE(left), neg, neg_one,
+ overflow_result);
+ }
+
+ ret = fold_build3_loc(this->location().gcc_location(), COND_EXPR,
+ TREE_TYPE(left), compare, ret, overflow_result);
if (eval_saved != NULL_TREE)
- ret = fold_build2_loc(this->location(), COMPOUND_EXPR,
+ ret = fold_build2_loc(this->location().gcc_location(), COMPOUND_EXPR,
TREE_TYPE(ret), eval_saved, ret);
}
Expression*
Expression::make_binary(Operator op, Expression* left, Expression* right,
- source_location location)
+ Location location)
{
return new Binary_expression(op, left, right, location);
}
Expression::comparison_tree(Translate_context* context, Operator op,
Type* left_type, tree left_tree,
Type* right_type, tree right_tree,
- source_location location)
+ Location location)
{
enum tree_code code;
switch (op)
else if (TREE_ADDRESSABLE(TREE_TYPE(right_tree)) || DECL_P(right_tree))
{
make_tmp = NULL_TREE;
- arg = build_fold_addr_expr_loc(location, right_tree);
+ arg = build_fold_addr_expr_loc(location.gcc_location(), right_tree);
if (DECL_P(right_tree))
TREE_ADDRESSABLE(right_tree) = 1;
}
DECL_INITIAL(tmp) = right_tree;
TREE_ADDRESSABLE(tmp) = 1;
make_tmp = build1(DECL_EXPR, void_type_node, tmp);
- SET_EXPR_LOCATION(make_tmp, location);
- arg = build_fold_addr_expr_loc(location, tmp);
+ SET_EXPR_LOCATION(make_tmp, location.gcc_location());
+ arg = build_fold_addr_expr_loc(location.gcc_location(), tmp);
}
- arg = fold_convert_loc(location, ptr_type_node, arg);
+ arg = fold_convert_loc(location.gcc_location(), ptr_type_node, arg);
tree descriptor = right_type->type_descriptor_pointer(context->gogo(),
location);
tree ret = fold_build2(code, boolean_type_node, left_tree, right_tree);
if (CAN_HAVE_LOCATION_P(ret))
- SET_EXPR_LOCATION(ret, location);
+ SET_EXPR_LOCATION(ret, location.gcc_location());
return ret;
}
Bound_method_expression*
Expression::make_bound_method(Expression* expr, Named_object* method,
- source_location location)
+ Location location)
{
return new Bound_method_expression(expr, method, location);
}
{
public:
Builtin_call_expression(Gogo* gogo, Expression* fn, Expression_list* args,
- bool is_varargs, source_location location);
+ bool is_varargs, Location location);
protected:
// This overrides Call_expression::do_lower.
Expression* fn,
Expression_list* args,
bool is_varargs,
- source_location location)
+ Location location)
: Call_expression(fn, args, is_varargs, location),
gogo_(gogo), code_(BUILTIN_INVALID), seen_(false)
{
if (this->classification() == EXPRESSION_ERROR)
return this;
- source_location loc = this->location();
+ Location loc = this->location();
if (this->is_varargs() && this->code_ != BUILTIN_APPEND)
{
Expression*
Builtin_call_expression::lower_make()
{
- source_location loc = this->location();
+ Location loc = this->location();
const Expression_list* args = this->args();
if (args == NULL || args->size() < 1)
return Expression::make_error(this->location());
}
- source_location type_loc = first_arg->location();
+ Location type_loc = first_arg->location();
Expression* type_arg;
if (is_slice || is_chan)
type_arg = Expression::make_type_descriptor(type, type_loc);
return Type::make_void_type();
case BUILTIN_RECOVER:
- return Type::make_interface_type(NULL, BUILTINS_LOCATION);
+ return Type::make_interface_type(NULL, Linemap::predeclared_location());
case BUILTIN_APPEND:
{
Builtin_call_expression::do_get_tree(Translate_context* context)
{
Gogo* gogo = context->gogo();
- source_location location = this->location();
+ Location location = this->location();
switch (this->code_)
{
case BUILTIN_INVALID:
fnname = "__go_print_uint64";
Type* itype = Type::lookup_integer_type("uint64");
Btype* bitype = itype->get_backend(gogo);
- arg = fold_convert_loc(location, type_to_tree(bitype), arg);
+ arg = fold_convert_loc(location.gcc_location(),
+ type_to_tree(bitype), arg);
}
else if (type->integer_type() != NULL)
{
fnname = "__go_print_int64";
Type* itype = Type::lookup_integer_type("int64");
Btype* bitype = itype->get_backend(gogo);
- arg = fold_convert_loc(location, type_to_tree(bitype), arg);
+ arg = fold_convert_loc(location.gcc_location(),
+ type_to_tree(bitype), arg);
}
else if (type->float_type() != NULL)
{
static tree print_double_fndecl;
pfndecl = &print_double_fndecl;
fnname = "__go_print_double";
- arg = fold_convert_loc(location, double_type_node, arg);
+ arg = fold_convert_loc(location.gcc_location(),
+ double_type_node, arg);
}
else if (type->complex_type() != NULL)
{
static tree print_complex_fndecl;
pfndecl = &print_complex_fndecl;
fnname = "__go_print_complex";
- arg = fold_convert_loc(location, complex_double_type_node,
- arg);
+ arg = fold_convert_loc(location.gcc_location(),
+ complex_double_type_node, arg);
}
else if (type->is_boolean_type())
{
static tree print_pointer_fndecl;
pfndecl = &print_pointer_fndecl;
fnname = "__go_print_pointer";
- arg = fold_convert_loc(location, ptr_type_node, arg);
+ arg = fold_convert_loc(location.gcc_location(),
+ ptr_type_node, arg);
}
else if (type->interface_type() != NULL)
{
tree arg_tree = arg->get_tree(context);
if (arg_tree == error_mark_node)
return error_mark_node;
- Type *empty = Type::make_interface_type(NULL, BUILTINS_LOCATION);
+ Type *empty =
+ Type::make_interface_type(NULL, Linemap::predeclared_location());
arg_tree = Expression::convert_for_assignment(context, empty,
arg->type(),
arg_tree, location);
if (arg_tree == error_mark_node)
return error_mark_node;
- Type *empty = Type::make_interface_type(NULL, BUILTINS_LOCATION);
+ Type *empty =
+ Type::make_interface_type(NULL, Linemap::predeclared_location());
tree empty_tree = type_to_tree(empty->get_backend(context->gogo()));
Type* nil_type = Type::make_nil_type();
}
if (call == error_mark_node)
return error_mark_node;
- return fold_build3_loc(location, COND_EXPR, empty_tree, arg_tree,
- call, empty_nil_tree);
+ return fold_build3_loc(location.gcc_location(), COND_EXPR, empty_tree,
+ arg_tree, call, empty_nil_tree);
}
case BUILTIN_CLOSE:
arg1_len = save_expr(arg1_len);
arg2_len = save_expr(arg2_len);
- tree len = fold_build3_loc(location, COND_EXPR, TREE_TYPE(arg1_len),
- fold_build2_loc(location, LT_EXPR,
- boolean_type_node,
+ tree len = fold_build3_loc(location.gcc_location(), COND_EXPR,
+ TREE_TYPE(arg1_len),
+ fold_build2_loc(location.gcc_location(),
+ LT_EXPR, boolean_type_node,
arg1_len, arg2_len),
arg1_len, arg2_len);
len = save_expr(len);
if (element_type_tree == error_mark_node)
return error_mark_node;
tree element_size = TYPE_SIZE_UNIT(element_type_tree);
- tree bytecount = fold_convert_loc(location, TREE_TYPE(element_size),
- len);
- bytecount = fold_build2_loc(location, MULT_EXPR,
+ tree bytecount = fold_convert_loc(location.gcc_location(),
+ TREE_TYPE(element_size), len);
+ bytecount = fold_build2_loc(location.gcc_location(), MULT_EXPR,
TREE_TYPE(element_size),
bytecount, element_size);
- bytecount = fold_convert_loc(location, size_type_node, bytecount);
+ bytecount = fold_convert_loc(location.gcc_location(), size_type_node,
+ bytecount);
- arg1_val = fold_convert_loc(location, ptr_type_node, arg1_val);
- arg2_val = fold_convert_loc(location, ptr_type_node, arg2_val);
+ arg1_val = fold_convert_loc(location.gcc_location(), ptr_type_node,
+ arg1_val);
+ arg2_val = fold_convert_loc(location.gcc_location(), ptr_type_node,
+ arg2_val);
static tree copy_fndecl;
tree call = Gogo::call_builtin(©_fndecl,
if (call == error_mark_node)
return error_mark_node;
- return fold_build2_loc(location, COMPOUND_EXPR, TREE_TYPE(len),
- call, len);
+ return fold_build2_loc(location.gcc_location(), COMPOUND_EXPR,
+ TREE_TYPE(len), call, len);
}
case BUILTIN_APPEND:
element_size = TYPE_SIZE_UNIT(element_type_tree);
}
- arg2_val = fold_convert_loc(location, ptr_type_node, arg2_val);
- arg2_len = fold_convert_loc(location, size_type_node, arg2_len);
- element_size = fold_convert_loc(location, size_type_node,
+ arg2_val = fold_convert_loc(location.gcc_location(), ptr_type_node,
+ arg2_val);
+ arg2_len = fold_convert_loc(location.gcc_location(), size_type_node,
+ arg2_len);
+ element_size = fold_convert_loc(location.gcc_location(), size_type_node,
element_size);
if (arg2_val == error_mark_node
return error_mark_node;
go_assert(COMPLEX_FLOAT_TYPE_P(TREE_TYPE(arg_tree)));
if (this->code_ == BUILTIN_REAL)
- return fold_build1_loc(location, REALPART_EXPR,
+ return fold_build1_loc(location.gcc_location(), REALPART_EXPR,
TREE_TYPE(TREE_TYPE(arg_tree)),
arg_tree);
else
- return fold_build1_loc(location, IMAGPART_EXPR,
+ return fold_build1_loc(location.gcc_location(), IMAGPART_EXPR,
TREE_TYPE(TREE_TYPE(arg_tree)),
arg_tree);
}
go_assert(TYPE_MAIN_VARIANT(TREE_TYPE(r))
== TYPE_MAIN_VARIANT(TREE_TYPE(i)));
go_assert(SCALAR_FLOAT_TYPE_P(TREE_TYPE(r)));
- return fold_build2_loc(location, COMPLEX_EXPR,
+ return fold_build2_loc(location.gcc_location(), COMPLEX_EXPR,
build_complex_type(TREE_TYPE(r)),
r, i);
}
Call_expression::do_lower(Gogo* gogo, Named_object* function,
Statement_inserter* inserter, int)
{
- source_location loc = this->location();
+ Location loc = this->location();
// A type cast can look like a function call.
if (this->fn_->is_type_expression()
if (this->varargs_are_lowered_)
return;
- source_location loc = this->location();
+ Location loc = this->location();
go_assert(param_count > 0);
go_assert(varargs_type->is_slice_type());
{
// Check types here so that we get a better message.
Type* patype = (*pa)->type();
- source_location paloc = (*pa)->location();
+ Location paloc = (*pa)->location();
if (!this->check_argument_type(i, element_type, patype,
paloc, issued_error))
continue;
bool
Call_expression::check_argument_type(int i, const Type* parameter_type,
const Type* argument_type,
- source_location argument_location,
+ Location argument_location,
bool issued_error)
{
std::string reason;
return error_mark_node;
Gogo* gogo = context->gogo();
- source_location location = this->location();
+ Location location = this->location();
Func_expression* func = this->fn_->func_expression();
Interface_field_reference_expression* interface_method =
tree fnt = type_to_tree(fntype->get_backend(gogo));
if (fnt == error_mark_node)
return error_mark_node;
- fn = fold_convert_loc(location, fnt, fn);
+ fn = fold_convert_loc(location.gcc_location(), fnt, fn);
}
// This is to support builtin math functions when using 80387 math.
excess_type = NULL_TREE;
else
{
- fn = build_fold_addr_expr_loc(location, excess_fndecl);
+ fn = build_fold_addr_expr_loc(location.gcc_location(),
+ excess_fndecl);
for (int i = 0; i < nargs; ++i)
args[i] = ::convert(excess_type, args[i]);
}
fn, nargs, args);
delete[] args;
- SET_EXPR_LOCATION(ret, location);
+ SET_EXPR_LOCATION(ret, location.gcc_location());
if (has_closure)
{
if (TREE_TYPE(ret) == ptr_type_node)
{
tree t = type_to_tree(this->type()->base()->get_backend(gogo));
- ret = fold_convert_loc(location, t, ret);
+ ret = fold_convert_loc(location.gcc_location(), t, ret);
}
if (excess_type != NULL_TREE)
return call_tree;
}
- source_location loc = this->location();
+ Location loc = this->location();
tree field = TYPE_FIELDS(TREE_TYPE(call_tree));
size_t rc = this->result_count();
for (size_t i = 0; i < rc; ++i, field = DECL_CHAIN(field))
if (temp_tree == error_mark_node)
continue;
- tree val_tree = build3_loc(loc, COMPONENT_REF, TREE_TYPE(field),
- call_tree, field, NULL_TREE);
- tree set_tree = build2_loc(loc, MODIFY_EXPR, void_type_node, temp_tree,
- val_tree);
+ tree val_tree = build3_loc(loc.gcc_location(), COMPONENT_REF,
+ TREE_TYPE(field), call_tree, field, NULL_TREE);
+ tree set_tree = build2_loc(loc.gcc_location(), MODIFY_EXPR,
+ void_type_node, temp_tree, val_tree);
append_to_statement_list(set_tree, &stmt_list);
}
Call_expression*
Expression::make_call(Expression* fn, Expression_list* args, bool is_varargs,
- source_location location)
+ Location location)
{
return new Call_expression(fn, args, is_varargs, location);
}
Expression*
Index_expression::do_lower(Gogo*, Named_object*, Statement_inserter*, int)
{
- source_location location = this->location();
+ Location location = this->location();
Expression* left = this->left_;
Expression* start = this->start_;
Expression* end = this->end_;
Expression*
Expression::make_index(Expression* left, Expression* start, Expression* end,
- source_location location)
+ Location location)
{
return new Index_expression(left, start, end, location);
}
{
public:
Array_index_expression(Expression* array, Expression* start,
- Expression* end, source_location location)
+ Expression* end, Location location)
: Expression(EXPRESSION_ARRAY_INDEX, location),
array_(array), start_(start), end_(end), type_(NULL)
{ }
Array_index_expression::do_get_tree(Translate_context* context)
{
Gogo* gogo = context->gogo();
- source_location loc = this->location();
+ Location loc = this->location();
Array_type* array_type = this->array_->type()->array_type();
if (array_type == NULL)
bad_index = Expression::check_bounds(start_tree, length_type, bad_index,
loc);
- start_tree = fold_convert_loc(loc, length_type, start_tree);
- bad_index = fold_build2_loc(loc, TRUTH_OR_EXPR, boolean_type_node, bad_index,
- fold_build2_loc(loc,
+ start_tree = fold_convert_loc(loc.gcc_location(), length_type, start_tree);
+ bad_index = fold_build2_loc(loc.gcc_location(), TRUTH_OR_EXPR,
+ boolean_type_node, bad_index,
+ fold_build2_loc(loc.gcc_location(),
(this->end_ == NULL
? GE_EXPR
: GT_EXPR),
build3(COND_EXPR, void_type_node,
bad_index, crash, NULL_TREE),
start_tree);
- start_tree = fold_convert_loc(loc, sizetype, start_tree);
+ start_tree = fold_convert_loc(loc.gcc_location(), sizetype, start_tree);
if (array_type->length() != NULL)
{
if (element_type_tree == error_mark_node)
return error_mark_node;
tree element_size = TYPE_SIZE_UNIT(element_type_tree);
- tree offset = fold_build2_loc(loc, MULT_EXPR, sizetype,
+ tree offset = fold_build2_loc(loc.gcc_location(), MULT_EXPR, sizetype,
start_tree, element_size);
- tree ptr = fold_build2_loc(loc, POINTER_PLUS_EXPR,
+ tree ptr = fold_build2_loc(loc.gcc_location(), POINTER_PLUS_EXPR,
TREE_TYPE(values), values, offset);
return build_fold_indirect_ref(ptr);
}
tree capacity_tree = array_type->capacity_tree(gogo, array_tree);
if (capacity_tree == error_mark_node)
return error_mark_node;
- capacity_tree = fold_convert_loc(loc, length_type, capacity_tree);
+ capacity_tree = fold_convert_loc(loc.gcc_location(), length_type,
+ capacity_tree);
tree end_tree;
if (this->end_->is_nil_expression())
bad_index = Expression::check_bounds(end_tree, length_type, bad_index,
loc);
- end_tree = fold_convert_loc(loc, length_type, end_tree);
+ end_tree = fold_convert_loc(loc.gcc_location(), length_type, end_tree);
capacity_tree = save_expr(capacity_tree);
- tree bad_end = fold_build2_loc(loc, TRUTH_OR_EXPR, boolean_type_node,
- fold_build2_loc(loc, LT_EXPR,
- boolean_type_node,
+ tree bad_end = fold_build2_loc(loc.gcc_location(), TRUTH_OR_EXPR,
+ boolean_type_node,
+ fold_build2_loc(loc.gcc_location(),
+ LT_EXPR, boolean_type_node,
end_tree, start_tree),
- fold_build2_loc(loc, GT_EXPR,
- boolean_type_node,
+ fold_build2_loc(loc.gcc_location(),
+ GT_EXPR, boolean_type_node,
end_tree, capacity_tree));
- bad_index = fold_build2_loc(loc, TRUTH_OR_EXPR, boolean_type_node,
- bad_index, bad_end);
+ bad_index = fold_build2_loc(loc.gcc_location(), TRUTH_OR_EXPR,
+ boolean_type_node, bad_index, bad_end);
}
Type* element_type = array_type->element_type();
return error_mark_node;
tree element_size = TYPE_SIZE_UNIT(element_type_tree);
- tree offset = fold_build2_loc(loc, MULT_EXPR, sizetype,
- fold_convert_loc(loc, sizetype, start_tree),
+ tree offset = fold_build2_loc(loc.gcc_location(), MULT_EXPR, sizetype,
+ fold_convert_loc(loc.gcc_location(), sizetype,
+ start_tree),
element_size);
tree value_pointer = array_type->value_pointer_tree(gogo, array_tree);
if (value_pointer == error_mark_node)
return error_mark_node;
- value_pointer = fold_build2_loc(loc, POINTER_PLUS_EXPR,
+ value_pointer = fold_build2_loc(loc.gcc_location(), POINTER_PLUS_EXPR,
TREE_TYPE(value_pointer),
value_pointer, offset);
- tree result_length_tree = fold_build2_loc(loc, MINUS_EXPR, length_type,
- end_tree, start_tree);
+ tree result_length_tree = fold_build2_loc(loc.gcc_location(), MINUS_EXPR,
+ length_type, end_tree, start_tree);
- tree result_capacity_tree = fold_build2_loc(loc, MINUS_EXPR, length_type,
- capacity_tree, start_tree);
+ tree result_capacity_tree = fold_build2_loc(loc.gcc_location(), MINUS_EXPR,
+ length_type, capacity_tree,
+ start_tree);
tree struct_tree = type_to_tree(this->type()->get_backend(gogo));
go_assert(TREE_CODE(struct_tree) == RECORD_TYPE);
field = DECL_CHAIN(field);
go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__count") == 0);
elt->index = field;
- elt->value = fold_convert_loc(loc, TREE_TYPE(field), result_length_tree);
+ elt->value = fold_convert_loc(loc.gcc_location(), TREE_TYPE(field),
+ result_length_tree);
elt = VEC_quick_push(constructor_elt, init, NULL);
field = DECL_CHAIN(field);
go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__capacity") == 0);
elt->index = field;
- elt->value = fold_convert_loc(loc, TREE_TYPE(field), result_capacity_tree);
+ elt->value = fold_convert_loc(loc.gcc_location(), TREE_TYPE(field),
+ result_capacity_tree);
tree constructor = build_constructor(struct_tree, init);
&& TREE_CONSTANT(result_capacity_tree))
TREE_CONSTANT(constructor) = 1;
- return fold_build2_loc(loc, COMPOUND_EXPR, TREE_TYPE(constructor),
+ return fold_build2_loc(loc.gcc_location(), COMPOUND_EXPR,
+ TREE_TYPE(constructor),
build3(COND_EXPR, void_type_node,
bad_index, crash, NULL_TREE),
constructor);
Expression*
Expression::make_array_index(Expression* array, Expression* start,
- Expression* end, source_location location)
+ Expression* end, Location location)
{
// Taking a slice of a composite literal requires moving the literal
// onto the heap.
{
public:
String_index_expression(Expression* string, Expression* start,
- Expression* end, source_location location)
+ Expression* end, Location location)
: Expression(EXPRESSION_STRING_INDEX, location),
string_(string), start_(start), end_(end)
{ }
tree
String_index_expression::do_get_tree(Translate_context* context)
{
- source_location loc = this->location();
+ Location loc = this->location();
tree string_tree = this->string_->get_tree(context);
if (string_tree == error_mark_node)
bad_index = Expression::check_bounds(start_tree, length_type, bad_index,
loc);
- start_tree = fold_convert_loc(loc, length_type, start_tree);
+ start_tree = fold_convert_loc(loc.gcc_location(), length_type, start_tree);
int code = (this->end_ == NULL
? RUNTIME_ERROR_STRING_INDEX_OUT_OF_BOUNDS
if (this->end_ == NULL)
{
- bad_index = fold_build2_loc(loc, TRUTH_OR_EXPR, boolean_type_node,
- bad_index,
- fold_build2_loc(loc, GE_EXPR,
+ bad_index = fold_build2_loc(loc.gcc_location(), TRUTH_OR_EXPR,
+ boolean_type_node, bad_index,
+ fold_build2_loc(loc.gcc_location(), GE_EXPR,
boolean_type_node,
start_tree, length_tree));
tree bytes_tree = String_type::bytes_tree(context->gogo(), string_tree);
- tree ptr = fold_build2_loc(loc, POINTER_PLUS_EXPR, TREE_TYPE(bytes_tree),
+ tree ptr = fold_build2_loc(loc.gcc_location(), POINTER_PLUS_EXPR,
+ TREE_TYPE(bytes_tree),
bytes_tree,
- fold_convert_loc(loc, sizetype, start_tree));
- tree index = build_fold_indirect_ref_loc(loc, ptr);
+ fold_convert_loc(loc.gcc_location(), sizetype,
+ start_tree));
+ tree index = build_fold_indirect_ref_loc(loc.gcc_location(), ptr);
return build2(COMPOUND_EXPR, TREE_TYPE(index),
build3(COND_EXPR, void_type_node,
bad_index = Expression::check_bounds(end_tree, length_type,
bad_index, loc);
- end_tree = fold_convert_loc(loc, length_type, end_tree);
+ end_tree = fold_convert_loc(loc.gcc_location(), length_type,
+ end_tree);
}
static tree strslice_fndecl;
Expression*
Expression::make_string_index(Expression* string, Expression* start,
- Expression* end, source_location location)
+ Expression* end, Location location)
{
return new String_index_expression(string, start, end, location);
}
}
else
{
- tmp = build_decl(this->location(), VAR_DECL, create_tmp_var_name("M"),
+ tmp = build_decl(this->location().gcc_location(), VAR_DECL,
+ create_tmp_var_name("M"),
TREE_TYPE(index_tree));
DECL_EXTERNAL(tmp) = 0;
TREE_PUBLIC(tmp) = 0;
TREE_STATIC(tmp) = 1;
DECL_ARTIFICIAL(tmp) = 1;
if (!TREE_CONSTANT(index_tree))
- make_tmp = fold_build2_loc(this->location(), INIT_EXPR, void_type_node,
+ make_tmp = fold_build2_loc(this->location().gcc_location(),
+ INIT_EXPR, void_type_node,
tmp, index_tree);
else
{
}
rest_of_decl_compilation(tmp, 1, 0);
}
- tree tmpref = fold_convert_loc(this->location(), const_ptr_type_node,
- build_fold_addr_expr_loc(this->location(),
- tmp));
+ tree tmpref =
+ fold_convert_loc(this->location().gcc_location(), const_ptr_type_node,
+ build_fold_addr_expr_loc(this->location().gcc_location(),
+ tmp));
static tree map_index_fndecl;
tree call = Gogo::call_builtin(&map_index_fndecl,
return error_mark_node;
tree ptr_val_type_tree = build_pointer_type(val_type_tree);
- tree ret = fold_convert_loc(this->location(), ptr_val_type_tree, call);
+ tree ret = fold_convert_loc(this->location().gcc_location(),
+ ptr_val_type_tree, call);
if (make_tmp != NULL_TREE)
ret = build2(COMPOUND_EXPR, ptr_val_type_tree, make_tmp, ret);
return ret;
Map_index_expression*
Expression::make_map_index(Expression* map, Expression* index,
- source_location location)
+ Location location)
{
return new Map_index_expression(map, index, location);
}
Field_reference_expression*
Expression::make_field_reference(Expression* expr, unsigned int field_index,
- source_location location)
+ Location location)
{
return new Field_reference_expression(expr, field_index, location);
}
Expression*
Expression::make_interface_field_reference(Expression* expr,
const std::string& field,
- source_location location)
+ Location location)
{
return new Interface_field_reference_expression(expr, field, location);
}
{
public:
Selector_expression(Expression* left, const std::string& name,
- source_location location)
+ Location location)
: Parser_expression(EXPRESSION_SELECTOR, location),
left_(left), name_(name)
{ }
Expression*
Selector_expression::lower_method_expression(Gogo* gogo)
{
- source_location location = this->location();
+ Location location = this->location();
Type* type = this->left_->type();
const std::string& name(this->name_);
Expression*
Expression::make_selector(Expression* left, const std::string& name,
- source_location location)
+ Location location)
{
return new Selector_expression(left, name, location);
}
class Allocation_expression : public Expression
{
public:
- Allocation_expression(Type* type, source_location location)
+ Allocation_expression(Type* type, Location location)
: Expression(EXPRESSION_ALLOCATION, location),
type_(type)
{ }
// Make an allocation expression.
Expression*
-Expression::make_allocation(Type* type, source_location location)
+Expression::make_allocation(Type* type, Location location)
{
return new Allocation_expression(type, location);
}
{
public:
Struct_construction_expression(Type* type, Expression_list* vals,
- source_location location)
+ Location location)
: Expression(EXPRESSION_STRUCT_CONSTRUCTION, location),
type_(type), vals_(vals)
{ }
Expression*
Expression::make_struct_composite_literal(Type* type, Expression_list* vals,
- source_location location)
+ Location location)
{
go_assert(type->struct_type() != NULL);
return new Struct_construction_expression(type, vals, location);
protected:
Array_construction_expression(Expression_classification classification,
Type* type, Expression_list* vals,
- source_location location)
+ Location location)
: Expression(classification, location),
type_(type), vals_(vals)
{ }
{
public:
Fixed_array_construction_expression(Type* type, Expression_list* vals,
- source_location location)
+ Location location)
: Array_construction_expression(EXPRESSION_FIXED_ARRAY_CONSTRUCTION,
type, vals, location)
{
{
public:
Open_array_construction_expression(Type* type, Expression_list* vals,
- source_location location)
+ Location location)
: Array_construction_expression(EXPRESSION_OPEN_ARRAY_CONSTRUCTION,
type, vals, location)
{
if (is_constant_initializer)
{
- tree tmp = build_decl(this->location(), VAR_DECL,
+ tree tmp = build_decl(this->location().gcc_location(), VAR_DECL,
create_tmp_var_name("C"), TREE_TYPE(values));
DECL_EXTERNAL(tmp) = 0;
TREE_PUBLIC(tmp) = 0;
space = save_expr(space);
tree s = fold_convert(build_pointer_type(TREE_TYPE(values)), space);
- tree ref = build_fold_indirect_ref_loc(this->location(), s);
+ tree ref = build_fold_indirect_ref_loc(this->location().gcc_location(),
+ s);
TREE_THIS_NOTRAP(ref) = 1;
set = build2(MODIFY_EXPR, void_type_node, ref, values);
}
Expression*
Expression::make_slice_composite_literal(Type* type, Expression_list* vals,
- source_location location)
+ Location location)
{
go_assert(type->is_slice_type());
return new Open_array_construction_expression(type, vals, location);
{
public:
Map_construction_expression(Type* type, Expression_list* vals,
- source_location location)
+ Location location)
: Expression(EXPRESSION_MAP_CONSTRUCTION, location),
type_(type), vals_(vals)
{ go_assert(vals == NULL || vals->size() % 2 == 0); }
Map_construction_expression::do_get_tree(Translate_context* context)
{
Gogo* gogo = context->gogo();
- source_location loc = this->location();
+ Location loc = this->location();
Map_type* mt = this->type_->map_type();
tree key_type_tree = type_to_tree(key_type->get_backend(gogo));
if (key_type_tree == error_mark_node)
return error_mark_node;
- tree key_field = build_decl(loc, FIELD_DECL, id, key_type_tree);
+ tree key_field = build_decl(loc.gcc_location(), FIELD_DECL, id,
+ key_type_tree);
DECL_CONTEXT(key_field) = struct_type;
TYPE_FIELDS(struct_type) = key_field;
tree val_type_tree = type_to_tree(val_type->get_backend(gogo));
if (val_type_tree == error_mark_node)
return error_mark_node;
- tree val_field = build_decl(loc, FIELD_DECL, id, val_type_tree);
+ tree val_field = build_decl(loc.gcc_location(), FIELD_DECL, id,
+ val_type_tree);
DECL_CONTEXT(val_field) = struct_type;
DECL_CHAIN(key_field) = val_field;
{
tmp = create_tmp_var(array_type, get_name(array_type));
DECL_INITIAL(tmp) = init;
- make_tmp = fold_build1_loc(loc, DECL_EXPR, void_type_node, tmp);
+ make_tmp = fold_build1_loc(loc.gcc_location(), DECL_EXPR,
+ void_type_node, tmp);
TREE_ADDRESSABLE(tmp) = 1;
}
else
{
- tmp = build_decl(loc, VAR_DECL, create_tmp_var_name("M"), array_type);
+ tmp = build_decl(loc.gcc_location(), VAR_DECL,
+ create_tmp_var_name("M"), array_type);
DECL_EXTERNAL(tmp) = 0;
TREE_PUBLIC(tmp) = 0;
TREE_STATIC(tmp) = 1;
DECL_ARTIFICIAL(tmp) = 1;
if (!TREE_CONSTANT(init))
- make_tmp = fold_build2_loc(loc, INIT_EXPR, void_type_node, tmp,
- init);
+ make_tmp = fold_build2_loc(loc.gcc_location(), INIT_EXPR,
+ void_type_node, tmp, init);
else
{
TREE_READONLY(tmp) = 1;
if (make_tmp == NULL)
ret = call;
else
- ret = fold_build2_loc(loc, COMPOUND_EXPR, type_tree, make_tmp, call);
+ ret = fold_build2_loc(loc.gcc_location(), COMPOUND_EXPR, type_tree,
+ make_tmp, call);
return ret;
}
{
public:
Composite_literal_expression(Type* type, int depth, bool has_keys,
- Expression_list* vals, source_location location)
+ Expression_list* vals, Location location)
: Parser_expression(EXPRESSION_COMPOSITE_LITERAL, location),
type_(type), depth_(depth), vals_(vals), has_keys_(has_keys)
{ }
Expression*
Composite_literal_expression::lower_struct(Gogo* gogo, Type* type)
{
- source_location location = this->location();
+ Location location = this->location();
Struct_type* st = type->struct_type();
if (this->vals_ == NULL || !this->has_keys_)
return new Struct_construction_expression(type, this->vals_, location);
Expression*
Composite_literal_expression::lower_array(Type* type)
{
- source_location location = this->location();
+ Location location = this->location();
if (this->vals_ == NULL || !this->has_keys_)
return this->make_array(type, this->vals_);
Expression*
Composite_literal_expression::make_array(Type* type, Expression_list* vals)
{
- source_location location = this->location();
+ Location location = this->location();
Array_type* at = type->array_type();
if (at->length() != NULL && at->length()->is_nil_expression())
{
Statement_inserter* inserter,
Type* type)
{
- source_location location = this->location();
+ Location location = this->location();
if (this->vals_ != NULL)
{
if (!this->has_keys_)
Expression*
Expression::make_composite_literal(Type* type, int depth, bool has_keys,
Expression_list* vals,
- source_location location)
+ Location location)
{
return new Composite_literal_expression(type, depth, has_keys, vals,
location);
Expression*
Expression::make_type_guard(Expression* expr, Type* type,
- source_location location)
+ Location location)
{
return new Type_guard_expression(expr, type, location);
}
class Heap_composite_expression : public Expression
{
public:
- Heap_composite_expression(Expression* expr, source_location location)
+ Heap_composite_expression(Expression* expr, Location location)
: Expression(EXPRESSION_HEAP_COMPOSITE, location),
expr_(expr)
{ }
expr_size, this->location());
space = fold_convert(build_pointer_type(TREE_TYPE(expr_tree)), space);
space = save_expr(space);
- tree ref = build_fold_indirect_ref_loc(this->location(), space);
+ tree ref = build_fold_indirect_ref_loc(this->location().gcc_location(),
+ space);
TREE_THIS_NOTRAP(ref) = 1;
tree ret = build2(COMPOUND_EXPR, TREE_TYPE(space),
build2(MODIFY_EXPR, void_type_node, ref, expr_tree),
space);
- SET_EXPR_LOCATION(ret, this->location());
+ SET_EXPR_LOCATION(ret, this->location().gcc_location());
return ret;
}
// Allocate a composite literal on the heap.
Expression*
-Expression::make_heap_composite(Expression* expr, source_location location)
+Expression::make_heap_composite(Expression* expr, Location location)
{
return new Heap_composite_expression(expr, location);
}
// Make a receive expression.
Receive_expression*
-Expression::make_receive(Expression* channel, source_location location)
+Expression::make_receive(Expression* channel, Location location)
{
return new Receive_expression(channel, location);
}
class Type_descriptor_expression : public Expression
{
public:
- Type_descriptor_expression(Type* type, source_location location)
+ Type_descriptor_expression(Type* type, Location location)
: Expression(EXPRESSION_TYPE_DESCRIPTOR, location),
type_(type)
{ }
// Make a type descriptor expression.
Expression*
-Expression::make_type_descriptor(Type* type, source_location location)
+Expression::make_type_descriptor(Type* type, Location location)
{
return new Type_descriptor_expression(type, location);
}
{
public:
Type_info_expression(Type* type, Type_info type_info)
- : Expression(EXPRESSION_TYPE_INFO, BUILTINS_LOCATION),
+ : Expression(EXPRESSION_TYPE_INFO, Linemap::predeclared_location()),
type_(type), type_info_(type_info)
{ }
{
public:
Struct_field_offset_expression(Struct_type* type, const Struct_field* field)
- : Expression(EXPRESSION_STRUCT_FIELD_OFFSET, BUILTINS_LOCATION),
+ : Expression(EXPRESSION_STRUCT_FIELD_OFFSET,
+ Linemap::predeclared_location()),
type_(type), field_(field)
{ }
class Map_descriptor_expression : public Expression
{
public:
- Map_descriptor_expression(Map_type* type, source_location location)
+ Map_descriptor_expression(Map_type* type, Location location)
: Expression(EXPRESSION_MAP_DESCRIPTOR, location),
type_(type)
{ }
// Make a map descriptor expression.
Expression*
-Expression::make_map_descriptor(Map_type* type, source_location location)
+Expression::make_map_descriptor(Map_type* type, Location location)
{
return new Map_descriptor_expression(type, location);
}
class Label_addr_expression : public Expression
{
public:
- Label_addr_expression(Label* label, source_location location)
+ Label_addr_expression(Label* label, Location location)
: Expression(EXPRESSION_LABEL_ADDR, location),
label_(label)
{ }
// Make an expression for the address of an unnamed label.
Expression*
-Expression::make_label_addr(Label* label, source_location location)
+Expression::make_label_addr(Label* label, Location location)
{
return new Label_addr_expression(label, location);
}
EXPRESSION_LABEL_ADDR
};
- Expression(Expression_classification, source_location);
+ Expression(Expression_classification, Location);
virtual ~Expression();
// Make an error expression. This is used when a parse error occurs
// to prevent cascading errors.
static Expression*
- make_error(source_location);
+ make_error(Location);
// Make an expression which is really a type. This is used during
// parsing.
static Expression*
- make_type(Type*, source_location);
+ make_type(Type*, Location);
// Make a unary expression.
static Expression*
- make_unary(Operator, Expression*, source_location);
+ make_unary(Operator, Expression*, Location);
// Make a binary expression.
static Expression*
- make_binary(Operator, Expression*, Expression*, source_location);
+ make_binary(Operator, Expression*, Expression*, Location);
// Make a reference to a constant in an expression.
static Expression*
- make_const_reference(Named_object*, source_location);
+ make_const_reference(Named_object*, Location);
// Make a reference to a variable in an expression.
static Expression*
- make_var_reference(Named_object*, source_location);
+ make_var_reference(Named_object*, Location);
// Make a reference to a temporary variable. Temporary variables
// are always created by a single statement, which is what we use to
// refer to them.
static Temporary_reference_expression*
- make_temporary_reference(Temporary_statement*, source_location);
+ make_temporary_reference(Temporary_statement*, Location);
// Make a sink expression--a reference to the blank identifier _.
static Expression*
- make_sink(source_location);
+ make_sink(Location);
// Make a reference to a function in an expression.
static Expression*
- make_func_reference(Named_object*, Expression* closure, source_location);
+ make_func_reference(Named_object*, Expression* closure, Location);
// Make a reference to an unknown name. In a correct program this
// will always be lowered to a real const/var/func reference.
static Expression*
- make_unknown_reference(Named_object*, source_location);
+ make_unknown_reference(Named_object*, Location);
// Make a constant bool expression.
static Expression*
- make_boolean(bool val, source_location);
+ make_boolean(bool val, Location);
// Make a constant string expression.
static Expression*
- make_string(const std::string&, source_location);
+ make_string(const std::string&, Location);
// Make a constant integer expression. TYPE should be NULL for an
// abstract type.
static Expression*
- make_integer(const mpz_t*, Type*, source_location);
+ make_integer(const mpz_t*, Type*, Location);
// Make a constant float expression. TYPE should be NULL for an
// abstract type.
static Expression*
- make_float(const mpfr_t*, Type*, source_location);
+ make_float(const mpfr_t*, Type*, Location);
// Make a constant complex expression. TYPE should be NULL for an
// abstract type.
static Expression*
- make_complex(const mpfr_t* real, const mpfr_t* imag, Type*, source_location);
+ make_complex(const mpfr_t* real, const mpfr_t* imag, Type*, Location);
// Make a nil expression.
static Expression*
- make_nil(source_location);
+ make_nil(Location);
// Make an iota expression. This is used for the predeclared
// constant iota.
// Make a call expression.
static Call_expression*
make_call(Expression* func, Expression_list* args, bool is_varargs,
- source_location);
+ Location);
// Make a reference to a specific result of a call expression which
// returns a tuple.
// Make an expression which is a method bound to its first
// parameter.
static Bound_method_expression*
- make_bound_method(Expression* object, Named_object* method, source_location);
+ make_bound_method(Expression* object, Named_object* method, Location);
// Make an index or slice expression. This is a parser expression
// which represents LEFT[START:END]. END may be NULL, meaning an
// string index, or a map index.
static Expression*
make_index(Expression* left, Expression* start, Expression* end,
- source_location);
+ Location);
// Make an array index expression. END may be NULL, in which case
// this is an lvalue.
static Expression*
make_array_index(Expression* array, Expression* start, Expression* end,
- source_location);
+ Location);
// Make a string index expression. END may be NULL. This is never
// an lvalue.
static Expression*
make_string_index(Expression* string, Expression* start, Expression* end,
- source_location);
+ Location);
// Make a map index expression. This is an lvalue.
static Map_index_expression*
- make_map_index(Expression* map, Expression* val, source_location);
+ make_map_index(Expression* map, Expression* val, Location);
// Make a selector. This is a parser expression which represents
// LEFT.NAME. At parse time we may not know the type of the left
// hand side.
static Expression*
- make_selector(Expression* left, const std::string& name, source_location);
+ make_selector(Expression* left, const std::string& name, Location);
// Make a reference to a field in a struct.
static Field_reference_expression*
- make_field_reference(Expression*, unsigned int field_index, source_location);
+ make_field_reference(Expression*, unsigned int field_index, Location);
// Make a reference to a field of an interface, with an associated
// object.
static Expression*
make_interface_field_reference(Expression*, const std::string&,
- source_location);
+ Location);
// Make an allocation expression.
static Expression*
- make_allocation(Type*, source_location);
+ make_allocation(Type*, Location);
// Make a type guard expression.
static Expression*
- make_type_guard(Expression*, Type*, source_location);
+ make_type_guard(Expression*, Type*, Location);
// Make a type cast expression.
static Expression*
- make_cast(Type*, Expression*, source_location);
+ make_cast(Type*, Expression*, Location);
// Make an unsafe type cast expression. This is only used when
// passing parameter to builtin functions that are part of the Go
// runtime.
static Expression*
- make_unsafe_cast(Type*, Expression*, source_location);
+ make_unsafe_cast(Type*, Expression*, Location);
// Make a composite literal. The DEPTH parameter is how far down we
// are in a list of composite literals with omitted types.
static Expression*
make_composite_literal(Type*, int depth, bool has_keys, Expression_list*,
- source_location);
+ Location);
// Make a struct composite literal.
static Expression*
- make_struct_composite_literal(Type*, Expression_list*, source_location);
+ make_struct_composite_literal(Type*, Expression_list*, Location);
// Make a slice composite literal.
static Expression*
- make_slice_composite_literal(Type*, Expression_list*, source_location);
+ make_slice_composite_literal(Type*, Expression_list*, Location);
// Take a composite literal and allocate it on the heap.
static Expression*
- make_heap_composite(Expression*, source_location);
+ make_heap_composite(Expression*, Location);
// Make a receive expression. VAL is NULL for a unary receive.
static Receive_expression*
- make_receive(Expression* channel, source_location);
+ make_receive(Expression* channel, Location);
// Make an expression which evaluates to the address of the type
// descriptor for TYPE.
static Expression*
- make_type_descriptor(Type* type, source_location);
+ make_type_descriptor(Type* type, Location);
// Make an expression which evaluates to some characteristic of a
// type. These are only used for type descriptors, so there is no
// Make an expression which evaluates to the address of the map
// descriptor for TYPE.
static Expression*
- make_map_descriptor(Map_type* type, source_location);
+ make_map_descriptor(Map_type* type, Location);
// Make an expression which evaluates to the address of an unnamed
// label.
static Expression*
- make_label_addr(Label*, source_location);
+ make_label_addr(Label*, Location);
// Return the expression classification.
Expression_classification
{ return this->classification_; }
// Return the location of the expression.
- source_location
+ Location
location() const
{ return this->location_; }
// assignment.
static tree
convert_for_assignment(Translate_context*, Type* lhs_type, Type* rhs_type,
- tree rhs_tree, source_location location);
+ tree rhs_tree, Location location);
// Return a tree converting a value of one interface type to another
// interface type. If FOR_TYPE_GUARD is true this is for a type
static tree
convert_interface_to_interface(Translate_context*, Type* lhs_type,
Type* rhs_type, tree rhs_tree,
- bool for_type_guard, source_location);
+ bool for_type_guard, Location);
// Return a tree implementing the comparison LHS_TREE OP RHS_TREE.
// TYPE is the type of both sides.
static tree
comparison_tree(Translate_context*, Operator op, Type* left_type,
tree left_tree, Type* right_type, tree right_tree,
- source_location);
+ Location);
// Return a tree for the multi-precision integer VAL in TYPE.
static tree
// BOUND_TYPE. If SOFAR is not NULL, it is or'red into the result.
// The return value may be NULL if SOFAR is NULL.
static tree
- check_bounds(tree val, tree bound_type, tree sofar, source_location);
+ check_bounds(tree val, tree bound_type, tree sofar, Location);
// Dump an expression to a dump constext.
void
static tree
convert_type_to_interface(Translate_context*, Type*, Type*, tree,
- source_location);
+ Location);
static tree
get_interface_type_descriptor(Translate_context*, Type*, tree,
- source_location);
+ Location);
static tree
convert_interface_to_type(Translate_context*, Type*, Type*, tree,
- source_location);
+ Location);
// The expression classification.
Expression_classification classification_;
// The location in the input file.
- source_location location_;
+ Location location_;
};
// A list of Expressions.
{
public:
Parser_expression(Expression_classification classification,
- source_location location)
+ Location location)
: Expression(classification, location)
{ }
class Var_expression : public Expression
{
public:
- Var_expression(Named_object* variable, source_location location)
+ Var_expression(Named_object* variable, Location location)
: Expression(EXPRESSION_VAR_REFERENCE, location),
variable_(variable)
{ }
{
public:
Temporary_reference_expression(Temporary_statement* statement,
- source_location location)
+ Location location)
: Expression(EXPRESSION_TEMPORARY_REFERENCE, location),
statement_(statement), is_lvalue_(false)
{ }
class String_expression : public Expression
{
public:
- String_expression(const std::string& val, source_location location)
+ String_expression(const std::string& val, Location location)
: Expression(EXPRESSION_STRING, location),
val_(val), type_(NULL)
{ }
{
public:
Binary_expression(Operator op, Expression* left, Expression* right,
- source_location location)
+ Location location)
: Expression(EXPRESSION_BINARY, location),
op_(op), left_(left), right_(right)
{ }
// if this could be done, false if not.
static bool
eval_integer(Operator op, Type* left_type, mpz_t left_val,
- Type* right_type, mpz_t right_val, source_location,
+ Type* right_type, mpz_t right_val, Location,
mpz_t val);
// Apply binary opcode OP to LEFT_VAL and RIGHT_VAL, setting VAL.
static bool
eval_float(Operator op, Type* left_type, mpfr_t left_val,
Type* right_type, mpfr_t right_val, mpfr_t val,
- source_location);
+ Location);
// Apply binary opcode OP to LEFT_REAL/LEFT_IMAG and
// RIGHT_REAL/RIGHT_IMAG, setting REAL/IMAG. Return true if this
static bool
eval_complex(Operator op, Type* left_type, mpfr_t left_real,
mpfr_t left_imag, Type* right_type, mpfr_t right_real,
- mpfr_t right_imag, mpfr_t real, mpfr_t imag, source_location);
+ mpfr_t right_imag, mpfr_t real, mpfr_t imag, Location);
// Compare integer constants according to OP.
static bool
// Report an error if OP can not be applied to TYPE. Return whether
// it can.
static bool
- check_operator_type(Operator op, Type* type, source_location);
+ check_operator_type(Operator op, Type* type, Location);
protected:
int
{
public:
Call_expression(Expression* fn, Expression_list* args, bool is_varargs,
- source_location location)
+ Location location)
: Expression(EXPRESSION_CALL, location),
fn_(fn), args_(args), type_(NULL), results_(NULL), tree_(NULL),
is_varargs_(is_varargs), are_hidden_fields_ok_(false),
private:
bool
- check_argument_type(int, const Type*, const Type*, source_location, bool);
+ check_argument_type(int, const Type*, const Type*, Location, bool);
tree
interface_method_function(Translate_context*,
{
public:
Func_expression(Named_object* function, Expression* closure,
- source_location location)
+ Location location)
: Expression(EXPRESSION_FUNC_REFERENCE, location),
function_(function), closure_(closure)
{ }
class Unknown_expression : public Parser_expression
{
public:
- Unknown_expression(Named_object* named_object, source_location location)
+ Unknown_expression(Named_object* named_object, Location location)
: Parser_expression(EXPRESSION_UNKNOWN_REFERENCE, location),
named_object_(named_object), is_composite_literal_key_(false)
{ }
{
public:
Index_expression(Expression* left, Expression* start, Expression* end,
- source_location location)
+ Location location)
: Parser_expression(EXPRESSION_INDEX, location),
left_(left), start_(start), end_(end), is_lvalue_(false)
{ }
{
public:
Map_index_expression(Expression* map, Expression* index,
- source_location location)
+ Location location)
: Expression(EXPRESSION_MAP_INDEX, location),
map_(map), index_(index), is_lvalue_(false),
is_in_tuple_assignment_(false)
{
public:
Bound_method_expression(Expression* expr, Named_object* method,
- source_location location)
+ Location location)
: Expression(EXPRESSION_BOUND_METHOD, location),
expr_(expr), expr_type_(NULL), method_(method)
{ }
{
public:
Field_reference_expression(Expression* expr, unsigned int field_index,
- source_location location)
+ Location location)
: Expression(EXPRESSION_FIELD_REFERENCE, location),
expr_(expr), field_index_(field_index)
{ }
public:
Interface_field_reference_expression(Expression* expr,
const std::string& name,
- source_location location)
+ Location location)
: Expression(EXPRESSION_INTERFACE_FIELD_REFERENCE, location),
expr_(expr), name_(name)
{ }
class Type_guard_expression : public Expression
{
public:
- Type_guard_expression(Expression* expr, Type* type, source_location location)
+ Type_guard_expression(Expression* expr, Type* type, Location location)
: Expression(EXPRESSION_TYPE_GUARD, location),
expr_(expr), type_(type)
{ }
class Receive_expression : public Expression
{
public:
- Receive_expression(Expression* channel, source_location location)
+ Receive_expression(Expression* channel, Location location)
: Expression(EXPRESSION_RECEIVE, location),
channel_(channel), for_select_(false)
{ }
--- /dev/null
+// go-linemap.h -- interface to location tracking -*- C++ -*-
+
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#ifndef GO_LINEMAP_H
+#define GO_LINEMAP_H
+
+#include "go-system.h"
+
+// The backend must define a type named Location which holds
+// information about a location in a source file. The only thing the
+// frontend does with instances of Location is pass them back to the
+// backend interface. The Location type must be assignable, and it
+// must be comparable: i.e., it must support operator= and operator<.
+// The type is normally passed by value rather than by reference, and
+// it should support that efficiently. The type should be defined in
+// "go-location.h".
+
+#include "go-location.h"
+
+// The Linemap class is a pure abstract interface, plus some static
+// convenience functions. The backend must implement the interface.
+
+class Linemap
+{
+ public:
+ Linemap()
+ {
+ // Only one instance of Linemap is allowed to exist.
+ go_assert(Linemap::instance_ == NULL);
+ Linemap::instance_ = this;
+ }
+
+ virtual
+ ~Linemap() { Linemap::instance_ = NULL; }
+
+ // Subsequent Location values will come from the file named
+ // FILE_NAME, starting at LINE_BEGIN. Normally LINE_BEGIN will be
+ // 0, but it will be non-zero if the Go source has a //line comment.
+ virtual void
+ start_file(const char* file_name, unsigned int line_begin) = 0;
+
+ // Subsequent Location values will come from the line LINE_NUMBER,
+ // in the current file. LINE_SIZE is the size of the line in bytes.
+ // This will normally be called for every line in a source file.
+ virtual void
+ start_line(unsigned int line_number, unsigned int line_size) = 0;
+
+ // Get a Location representing column position COLUMN on the current
+ // line in the current file.
+ virtual Location
+ get_location(unsigned int column) = 0;
+
+ // Stop generating Location values. This will be called after all
+ // input files have been read, in case any cleanup is required.
+ virtual void
+ stop() = 0;
+
+ protected:
+ // Return a special Location used for predeclared identifiers. This
+ // Location should be different from that for any actual source
+ // file. This location will be used for various different types,
+ // functions, and objects created by the frontend.
+ virtual Location
+ get_predeclared_location() = 0;
+
+ // Return a special Location which indicates that no actual location
+ // is known. This is used for undefined objects and for errors.
+ virtual Location
+ get_unknown_location() = 0;
+
+ // Return whether the argument is the Location returned by
+ // get_predeclared_location.
+ virtual bool
+ is_predeclared(Location) = 0;
+
+ // Return whether the argument is the Location returned by
+ // get_unknown_location.
+ virtual bool
+ is_unknown(Location) = 0;
+
+ // The single existing instance of Linemap.
+ static Linemap *instance_;
+
+ public:
+ // Following are convenience static functions, which allow us to
+ // access some virtual functions without explicitly passing around
+ // an instance of Linemap.
+
+ // Return the special Location used for predeclared identifiers.
+ static Location
+ predeclared_location()
+ {
+ go_assert(Linemap::instance_ != NULL);
+ return Linemap::instance_->get_predeclared_location();
+ }
+
+ // Return the special Location used when no location is known.
+ static Location
+ unknown_location()
+ {
+ go_assert(Linemap::instance_ != NULL);
+ return Linemap::instance_->get_unknown_location();
+ }
+
+ // Return whether the argument is the special location used for
+ // predeclared identifiers.
+ static bool
+ is_predeclared_location(Location loc)
+ {
+ go_assert(Linemap::instance_ != NULL);
+ return Linemap::instance_->is_predeclared(loc);
+ }
+
+ // Return whether the argument is the special location used when no
+ // location is known.
+ static bool
+ is_unknown_location(Location loc)
+ {
+ go_assert(Linemap::instance_ != NULL);
+ return Linemap::instance_->is_unknown(loc);
+ }
+};
+
+// The backend interface must define this function. It should return
+// a fully implemented instance of Linemap.
+extern Linemap* go_get_linemap();
+
+#endif // !defined(GO_LINEMAP_H)
go_create_gogo(int int_type_size, int pointer_size)
{
go_assert(::gogo == NULL);
- ::gogo = new Gogo(go_get_backend(), int_type_size, pointer_size);
+ Linemap* linemap = go_get_linemap();
+ ::gogo = new Gogo(go_get_backend(), linemap, int_type_size, pointer_size);
if (!unique_prefix.empty())
::gogo->set_unique_prefix(unique_prefix);
bool only_check_syntax, bool require_return_statement)
{
go_assert(filename_count > 0);
+
for (unsigned int i = 0; i < filename_count; ++i)
{
if (i > 0)
fatal_error("cannot open %s: %m", filename);
}
- Lex lexer(filename, file);
+ Lex lexer(filename, file, ::gogo->linemap());
Parse parse(&lexer, ::gogo);
parse.program();
fclose(file);
}
+ ::gogo->linemap()->stop();
+
::gogo->clear_file_scope();
// If the global predeclared names are referenced but not defined,
rest_of_decl_compilation(decl, 1, 0);
static tree register_gc_fndecl;
- tree call = Gogo::call_builtin(®ister_gc_fndecl, BUILTINS_LOCATION,
- "__go_register_gc_roots",
+ tree call = Gogo::call_builtin(®ister_gc_fndecl,
+ Linemap::predeclared_location(),
+ "__go_register_gc_roots",
1,
void_type_node,
build_pointer_type(root_list_type),
else if (is_sink)
var_init_tree = init;
else
- var_init_tree = fold_build2_loc(no->location(), MODIFY_EXPR,
- void_type_node, vec[i], init);
+ var_init_tree = fold_build2_loc(no->location().gcc_location(),
+ MODIFY_EXPR, void_type_node,
+ vec[i], init);
}
else
{
&& !this->func_declaration_value()->asm_name().empty())
decl_name = this->func_declaration_value()->asm_name();
else if (this->is_type()
- && this->type_value()->location() == BUILTINS_LOCATION)
+ && Linemap::is_predeclared_location(this->type_value()->location()))
{
// We don't need the package name for builtin types.
decl_name = Gogo::unpack_hidden_name(this->name_);
decl = error_mark_node;
else if (INTEGRAL_TYPE_P(TREE_TYPE(expr_tree)))
{
- decl = build_decl(named_constant->location(), CONST_DECL,
- name, TREE_TYPE(expr_tree));
+ decl = build_decl(named_constant->location().gcc_location(),
+ CONST_DECL, name, TREE_TYPE(expr_tree));
DECL_INITIAL(decl) = expr_tree;
TREE_CONSTANT(decl) = 1;
TREE_READONLY(decl) = 1;
// descriptor, even though we don't do anything with it.
if (this->package_ == NULL)
{
- named_type->type_descriptor_pointer(gogo, BUILTINS_LOCATION);
+ named_type->
+ type_descriptor_pointer(gogo,
+ Linemap::predeclared_location());
Type* pn = Type::make_pointer_type(named_type);
- pn->type_descriptor_pointer(gogo, BUILTINS_LOCATION);
+ pn->type_descriptor_pointer(gogo,
+ Linemap::predeclared_location());
}
}
}
else
push_cfun(DECL_STRUCT_FUNCTION(decl));
- cfun->function_end_locus = func->block()->end_location();
+ cfun->function_end_locus =
+ func->block()->end_location().gcc_location();
current_function_decl = decl;
this->location());
if (val == error_mark_node)
return error_mark_node;
- tree set = fold_build2_loc(this->location(), MODIFY_EXPR,
- void_type_node, var_decl, val);
+ tree set = fold_build2_loc(this->location().gcc_location(),
+ MODIFY_EXPR, void_type_node, var_decl,
+ val);
append_to_statement_list(set, &statements);
}
}
// want the real function type for a function declaration.
go_assert(POINTER_TYPE_P(functype));
functype = TREE_TYPE(functype);
- tree decl = build_decl(this->location(), FUNCTION_DECL, id, functype);
+ tree decl = build_decl(this->location().gcc_location(), FUNCTION_DECL,
+ id, functype);
this->fndecl_ = decl;
// Why do we have to do this in the frontend?
tree restype = TREE_TYPE(functype);
- tree resdecl = build_decl(this->location(), RESULT_DECL, NULL_TREE,
- restype);
+ tree resdecl =
+ build_decl(this->location().gcc_location(), RESULT_DECL, NULL_TREE,
+ restype);
DECL_ARTIFICIAL(resdecl) = 1;
DECL_IGNORED_P(resdecl) = 1;
DECL_CONTEXT(resdecl) = decl;
// want the real function type for a function declaration.
go_assert(POINTER_TYPE_P(functype));
functype = TREE_TYPE(functype);
- decl = build_decl(this->location(), FUNCTION_DECL, id, functype);
+ decl = build_decl(this->location().gcc_location(), FUNCTION_DECL, id,
+ functype);
TREE_PUBLIC(decl) = 1;
DECL_EXTERNAL(decl) = 1;
no->location());
space = save_expr(space);
space = fold_convert(build_pointer_type(val_type), space);
- tree spaceref = build_fold_indirect_ref_loc(no->location(), space);
+ tree spaceref = build_fold_indirect_ref_loc(no->location().gcc_location(),
+ space);
TREE_THIS_NOTRAP(spaceref) = 1;
tree set = fold_build2_loc(loc, MODIFY_EXPR, void_type_node,
spaceref, init);
if (var_decl == error_mark_node)
return error_mark_node;
go_assert(TREE_CODE(var_decl) == VAR_DECL);
- source_location loc = DECL_SOURCE_LOCATION(var_decl);
+ Location loc(DECL_SOURCE_LOCATION(var_decl));
std::string name = IDENTIFIER_POINTER(DECL_NAME(var_decl));
name += ".param";
go_assert(POINTER_TYPE_P(type));
type = TREE_TYPE(type);
- tree parm_decl = build_decl(loc, PARM_DECL, id, type);
+ tree parm_decl = build_decl(loc.gcc_location(), PARM_DECL, id, type);
DECL_CONTEXT(parm_decl) = current_function_decl;
DECL_ARG_TYPE(parm_decl) = type;
tree space = gogo->allocate_memory(no->var_value()->type(), size, loc);
space = save_expr(space);
space = fold_convert(TREE_TYPE(var_decl), space);
- tree spaceref = build_fold_indirect_ref_loc(loc, space);
+ tree spaceref = build_fold_indirect_ref_loc(loc.gcc_location(), space);
TREE_THIS_NOTRAP(spaceref) = 1;
tree init = build2(COMPOUND_EXPR, TREE_TYPE(space),
build2(MODIFY_EXPR, void_type_node, spaceref, parm_decl),
}
else
{
- source_location loc = (*p)->location();
+ Location loc = (*p)->location();
tree type_tree = type_to_tree(type->get_backend(gogo));
tree space = gogo->allocate_memory(type,
TYPE_SIZE_UNIT(type_tree),
loc);
tree ptr_type_tree = build_pointer_type(type_tree);
- init = fold_convert_loc(loc, ptr_type_tree, space);
+ init = fold_convert_loc(loc.gcc_location(), ptr_type_tree, space);
}
if (var_decl != error_mark_node)
// function.
if (defer_init != NULL_TREE && defer_init != error_mark_node)
{
- SET_EXPR_LOCATION(defer_init, this->block_->start_location());
+ SET_EXPR_LOCATION(defer_init,
+ this->block_->start_location().gcc_location());
append_to_statement_list(defer_init, &init);
// Clean up the defer stack when we leave the function.
Function::build_defer_wrapper(Gogo* gogo, Named_object* named_function,
tree *except, tree *fini)
{
- source_location end_loc = this->block_->end_location();
+ Location end_loc = this->block_->end_location();
// Add an exception handler. This is used if a panic occurs. Its
// purpose is to stop the stack unwinding if a deferred function
if (retval == NULL_TREE)
set = NULL_TREE;
else
- set = fold_build2_loc(end_loc, MODIFY_EXPR, void_type_node,
+ set = fold_build2_loc(end_loc.gcc_location(), MODIFY_EXPR, void_type_node,
DECL_RESULT(this->fndecl_), retval);
- tree ret_stmt = fold_build1_loc(end_loc, RETURN_EXPR, void_type_node, set);
+ tree ret_stmt = fold_build1_loc(end_loc.gcc_location(), RETURN_EXPR,
+ void_type_node, set);
append_to_statement_list(ret_stmt, &stmt_list);
go_assert(*except == NULL_TREE);
stmt_list = NULL;
- tree label = create_artificial_label(end_loc);
- tree define_label = fold_build1_loc(end_loc, LABEL_EXPR, void_type_node,
- label);
+ tree label = create_artificial_label(end_loc.gcc_location());
+ tree define_label = fold_build1_loc(end_loc.gcc_location(), LABEL_EXPR,
+ void_type_node, label);
append_to_statement_list(define_label, &stmt_list);
call = Runtime::make_call(Runtime::UNDEFER, end_loc, 1,
if (undefer == error_mark_node || defer == error_mark_node)
return;
- tree jump = fold_build1_loc(end_loc, GOTO_EXPR, void_type_node, label);
+ tree jump = fold_build1_loc(end_loc.gcc_location(), GOTO_EXPR, void_type_node,
+ label);
tree catch_body = build2(COMPOUND_EXPR, void_type_node, defer, jump);
catch_body = build2(CATCH_EXPR, void_type_node, NULL, catch_body);
tree try_catch = build2(TRY_CATCH_EXPR, void_type_node, undefer, catch_body);
// variable to true if we are returning from this function.
retval = this->return_value(gogo, named_function, end_loc,
&stmt_list);
- set = fold_build2_loc(end_loc, MODIFY_EXPR, void_type_node,
+ set = fold_build2_loc(end_loc.gcc_location(), MODIFY_EXPR, void_type_node,
DECL_RESULT(this->fndecl_), retval);
- ret_stmt = fold_build1_loc(end_loc, RETURN_EXPR, void_type_node, set);
+ ret_stmt = fold_build1_loc(end_loc.gcc_location(), RETURN_EXPR,
+ void_type_node, set);
Expression* ref =
Expression::make_temporary_reference(this->defer_stack_, end_loc);
tree tref = ref->get_tree(&context);
- tree s = build3_loc(end_loc, COND_EXPR, void_type_node, tref,
- ret_stmt, NULL_TREE);
+ tree s = build3_loc(end_loc.gcc_location(), COND_EXPR, void_type_node,
+ tref, ret_stmt, NULL_TREE);
append_to_statement_list(s, &stmt_list);
tree
Function::return_value(Gogo* gogo, Named_object* named_function,
- source_location location, tree* stmt_list) const
+ Location location, tree* stmt_list) const
{
const Typed_identifier_list* results = this->type_->results();
if (results == NULL || results->empty())
named_function);
tree ret = var_to_tree(bvar);
if (this->results_->front()->result_var_value()->is_in_heap())
- ret = build_fold_indirect_ref_loc(location, ret);
+ ret = build_fold_indirect_ref_loc(location.gcc_location(), ret);
return ret;
}
else
Bvariable* bvar = no->get_backend_variable(gogo, named_function);
tree val = var_to_tree(bvar);
if (no->result_var_value()->is_in_heap())
- val = build_fold_indirect_ref_loc(location, val);
- tree set = fold_build2_loc(location, MODIFY_EXPR, void_type_node,
+ val = build_fold_indirect_ref_loc(location.gcc_location(), val);
+ tree set = fold_build2_loc(location.gcc_location(), MODIFY_EXPR,
+ void_type_node,
build3(COMPONENT_REF, TREE_TYPE(field),
retval, field, NULL_TREE),
val);
// type TYPE.
tree
-Gogo::allocate_memory(Type* type, tree size, source_location location)
+Gogo::allocate_memory(Type* type, tree size, Location location)
{
// If the package imports unsafe, then it may play games with
// pointers that look like integers.
td_type = type;
else
td_type = Type::make_pointer_type(type);
- tree tdp = td_type->type_descriptor_pointer(this, BUILTINS_LOCATION);
+ tree tdp = td_type->type_descriptor_pointer(this,
+ Linemap::predeclared_location());
elt->value = fold_convert(const_ptr_type_node, tdp);
size_t i = 1;
// Build a call to a builtin function.
tree
-Gogo::call_builtin(tree* pdecl, source_location location, const char* name,
+Gogo::call_builtin(tree* pdecl, Location location, const char* name,
int nargs, tree rettype, ...)
{
if (rettype == error_mark_node)
tree fnptr = build_fold_addr_expr(*pdecl);
if (CAN_HAVE_LOCATION_P(fnptr))
- SET_EXPR_LOCATION(fnptr, location);
+ SET_EXPR_LOCATION(fnptr, location.gcc_location());
tree ret = build_call_array(rettype, fnptr, nargs, args);
- SET_EXPR_LOCATION(ret, location);
+ SET_EXPR_LOCATION(ret, location.gcc_location());
delete[] types;
delete[] args;
// Build a call to the runtime error function.
tree
-Gogo::runtime_error(int code, source_location location)
+Gogo::runtime_error(int code, Location location)
{
static tree runtime_error_fndecl;
tree ret = Gogo::call_builtin(&runtime_error_fndecl,
tree
Gogo::receive_from_channel(tree type_tree, tree channel, bool for_select,
- source_location location)
+ Location location)
{
if (type_tree == error_mark_node || channel == error_mark_node)
return error_mark_node;
TREE_NOTHROW(receive_small_fndecl) = 0;
int bitsize = GET_MODE_BITSIZE(TYPE_MODE(type_tree));
tree int_type_tree = go_type_for_size(bitsize, 1);
- return fold_convert_loc(location, type_tree,
- fold_convert_loc(location, int_type_tree,
- call));
+ return fold_convert_loc(location.gcc_location(), type_tree,
+ fold_convert_loc(location.gcc_location(),
+ int_type_tree, call));
}
else
{
DECL_IGNORED_P(tmp) = 0;
TREE_ADDRESSABLE(tmp) = 1;
tree make_tmp = build1(DECL_EXPR, void_type_node, tmp);
- SET_EXPR_LOCATION(make_tmp, location);
+ SET_EXPR_LOCATION(make_tmp, location.gcc_location());
tree tmpaddr = build_fold_addr_expr(tmp);
tmpaddr = fold_convert(ptr_type_node, tmpaddr);
static tree receive_big_fndecl;
// Make a trampoline which calls FNADDR passing CLOSURE.
tree
-Gogo::make_trampoline(tree fnaddr, tree closure, source_location location)
+Gogo::make_trampoline(tree fnaddr, tree closure, Location location)
{
tree trampoline_type = Gogo::trampoline_type_tree();
tree trampoline_size = TYPE_SIZE_UNIT(trampoline_type);
size_type_node,
trampoline_size,
ptr_type_node,
- fold_convert_loc(location, ptr_type_node,
- closure));
+ fold_convert_loc(location.gcc_location(),
+ ptr_type_node, closure));
if (x == error_mark_node)
return error_mark_node;
// Class Gogo.
-Gogo::Gogo(Backend* backend, int int_type_size, int pointer_size)
+Gogo::Gogo(Backend* backend, Linemap* linemap, int int_type_size,
+ int pointer_size)
: backend_(backend),
+ linemap_(linemap),
package_(NULL),
functions_(),
globals_(new Bindings(NULL)),
interface_types_(),
named_types_are_converted_(false)
{
- const source_location loc = BUILTINS_LOCATION;
+ const Location loc = Linemap::predeclared_location();
Named_type* uint8_type = Type::make_integer_type("uint8", true, 8,
RUNTIME_TYPE_KIND_UINT8);
void
Gogo::set_package_name(const std::string& package_name,
- source_location location)
+ Location location)
{
if (this->package_ != NULL && this->package_->name() != package_name)
{
{
// Declare "main" as a function which takes no parameters and
// returns no value.
+ Location uloc = Linemap::unknown_location();
this->declare_function("main",
- Type::make_function_type(NULL, NULL, NULL,
- BUILTINS_LOCATION),
- BUILTINS_LOCATION);
+ Type::make_function_type (NULL, NULL, NULL, uloc),
+ uloc);
}
}
Gogo::import_package(const std::string& filename,
const std::string& local_name,
bool is_local_name_exported,
- source_location location)
+ Location location)
{
if (filename == "unsafe")
{
const std::string& alias_arg,
bool is_alias_exported,
const std::string& unique_prefix,
- source_location location,
+ Location location,
bool* padd_to_globals)
{
// FIXME: Now that we compile packages as a whole, should we permit
Named_object*
Gogo::add_package(const std::string& real_name, const std::string& alias,
- const std::string& unique_prefix, source_location location)
+ const std::string& unique_prefix, Location location)
{
go_assert(this->in_global_scope());
Package*
Gogo::register_package(const std::string& package_name,
const std::string& unique_prefix,
- source_location location)
+ Location location)
{
go_assert(!unique_prefix.empty() && !package_name.empty());
std::string name = unique_prefix + '.' + package_name;
go_assert(package != NULL);
go_assert(package->name() == package_name
&& package->unique_prefix() == unique_prefix);
- if (package->location() == UNKNOWN_LOCATION)
+ if (Linemap::is_unknown_location(package->location()))
package->set_location(location);
}
else
Named_object*
Gogo::start_function(const std::string& name, Function_type* type,
- bool add_method_to_type, source_location location)
+ bool add_method_to_type, Location location)
{
bool at_top_level = this->functions_.empty();
// Finish compiling a function.
void
-Gogo::finish_function(source_location location)
+Gogo::finish_function(Location location)
{
this->finish_block(location);
go_assert(this->functions_.back().blocks.empty());
// Start a new block.
void
-Gogo::start_block(source_location location)
+Gogo::start_block(Location location)
{
go_assert(!this->functions_.empty());
Block* block = new Block(this->current_block(), location);
// Finish a block.
Block*
-Gogo::finish_block(source_location location)
+Gogo::finish_block(Location location)
{
go_assert(!this->functions_.empty());
go_assert(!this->functions_.back().blocks.empty());
// Add an unknown name.
Named_object*
-Gogo::add_unknown_name(const std::string& name, source_location location)
+Gogo::add_unknown_name(const std::string& name, Location location)
{
return this->package_->bindings()->add_unknown_name(name, location);
}
Named_object*
Gogo::declare_function(const std::string& name, Function_type* type,
- source_location location)
+ Location location)
{
if (!type->is_method())
return this->current_bindings()->add_function_declaration(name, NULL, type,
Label*
Gogo::add_label_definition(const std::string& label_name,
- source_location location)
+ Location location)
{
go_assert(!this->functions_.empty());
Function* func = this->functions_.back().function->func_value();
Label*
Gogo::add_label_reference(const std::string& label_name,
- source_location location, bool issue_goto_errors)
+ Location location, bool issue_goto_errors)
{
go_assert(!this->functions_.empty());
Function* func = this->functions_.back().function->func_value();
// Return the current binding state.
Bindings_snapshot*
-Gogo::bindings_snapshot(source_location location)
+Gogo::bindings_snapshot(Location location)
{
return new Bindings_snapshot(this->current_block(), location);
}
// Add a block.
void
-Gogo::add_block(Block* block, source_location location)
+Gogo::add_block(Block* block, Location location)
{
go_assert(!this->functions_.empty()
&& !this->functions_.back().blocks.empty());
// Add a type.
void
-Gogo::add_type(const std::string& name, Type* type, source_location location)
+Gogo::add_type(const std::string& name, Type* type, Location location)
{
Named_object* no = this->current_bindings()->add_type(name, NULL, type,
location);
// Declare a type.
Named_object*
-Gogo::declare_type(const std::string& name, source_location location)
+Gogo::declare_type(const std::string& name, Location location)
{
Bindings* bindings = this->current_bindings();
Named_object* no = bindings->add_type_declaration(name, NULL, location);
// Declare a type at the package level.
Named_object*
-Gogo::declare_package_type(const std::string& name, source_location location)
+Gogo::declare_package_type(const std::string& name, Location location)
{
return this->package_->bindings()->add_type_declaration(name, NULL, location);
}
{
error_at(no->location(), "expected type");
Type* errtype = Type::make_error_type();
- Named_object* err = Named_object::make_type("error", NULL,
- errtype,
- BUILTINS_LOCATION);
+ Named_object* err =
+ Named_object::make_type("erroneous_type", NULL, errtype,
+ Linemap::predeclared_location());
no->set_type_value(err->type_value());
}
}
Binary_expression* shortcut = (*pshortcut)->binary_expression();
Expression* left = shortcut->left();
Expression* right = shortcut->right();
- source_location loc = shortcut->location();
+ Location loc = shortcut->location();
Block* retblock = new Block(enclosing, loc);
retblock->set_end_location(loc);
if (is_thunk && p + 1 == find_eval_ordering.end())
break;
- source_location loc = (*pexpr)->location();
+ Location loc = (*pexpr)->location();
Statement* s;
if ((*pexpr)->call_expression() == NULL
|| (*pexpr)->call_expression()->result_count() < 2)
++p)
{
Expression** pexpr = *p;
- source_location loc = (*pexpr)->location();
+ Location loc = (*pexpr)->location();
Statement* s;
if ((*pexpr)->call_expression() == NULL
|| (*pexpr)->call_expression()->result_count() < 2)
private:
Expression*
- can_recover_arg(source_location);
+ can_recover_arg(Location);
// General IR.
Gogo* gogo_;
return TRAVERSE_CONTINUE;
Gogo* gogo = this->gogo_;
- source_location location = orig_func->location();
+ Location location = orig_func->location();
static int count;
char buf[50];
// __go_can_recover(__builtin_return_address()).
Expression*
-Build_recover_thunks::can_recover_arg(source_location location)
+Build_recover_thunks::can_recover_arg(Location location)
{
static Named_object* builtin_return_address;
if (builtin_return_address == NULL)
{
- const source_location bloc = BUILTINS_LOCATION;
+ const Location bloc = Linemap::predeclared_location();
Typed_identifier_list* param_types = new Typed_identifier_list();
Type* uint_type = Type::lookup_integer_type("uint");
static Named_object* can_recover;
if (can_recover == NULL)
{
- const source_location bloc = BUILTINS_LOCATION;
+ const Location bloc = Linemap::predeclared_location();
Typed_identifier_list* param_types = new Typed_identifier_list();
Type* voidptr_type = Type::make_pointer_type(Type::make_void_type());
param_types->push_back(Typed_identifier("a", voidptr_type, bloc));
// Class Function.
Function::Function(Function_type* type, Function* enclosing, Block* block,
- source_location location)
+ Location location)
: type_(type), enclosing_(enclosing), results_(NULL),
closure_var_(NULL), block_(block), location_(location), fndecl_(NULL),
defer_stack_(NULL), results_are_named_(false), calls_recover_(false),
{
// We don't know the type of the variable yet. We add fields as
// we find them.
- source_location loc = this->type_->location();
+ Location loc = this->type_->location();
Struct_field_list* sfl = new Struct_field_list;
Type* struct_type = Type::make_struct_type(sfl, loc);
Variable* var = new Variable(Type::make_pointer_type(struct_type),
Label*
Function::add_label_definition(Gogo* gogo, const std::string& label_name,
- source_location location)
+ Location location)
{
Label* lnull = NULL;
std::pair<Labels::iterator, bool> ins =
Label*
Function::add_label_reference(Gogo* gogo, const std::string& label_name,
- source_location location, bool issue_goto_errors)
+ Location location, bool issue_goto_errors)
{
Label* lnull = NULL;
std::pair<Labels::iterator, bool> ins =
// function which uses defer.
Expression*
-Function::defer_stack(source_location location)
+Function::defer_stack(Location location)
{
if (this->defer_stack_ == NULL)
{
// Class Block.
-Block::Block(Block* enclosing, source_location location)
+Block::Block(Block* enclosing, Location location)
: enclosing_(enclosing), statements_(),
bindings_(new Bindings(enclosing == NULL
? NULL
// Class Bindings_snapshot.
-Bindings_snapshot::Bindings_snapshot(const Block* b, source_location location)
+Bindings_snapshot::Bindings_snapshot(const Block* b, Location location)
: block_(b), counts_(), location_(location)
{
while (b != NULL)
// Report errors appropriate for a goto from B to this.
void
-Bindings_snapshot::check_goto_from(const Block* b, source_location loc)
+Bindings_snapshot::check_goto_from(const Block* b, Location loc)
{
size_t dummy;
if (!this->check_goto_block(loc, b, this->block_, &dummy))
// BFROM.
bool
-Bindings_snapshot::check_goto_block(source_location loc, const Block* bfrom,
+Bindings_snapshot::check_goto_block(Location loc, const Block* bfrom,
const Block* bto, size_t* pindex)
{
// It is an error if BTO is not either BFROM or above BFROM.
// CTO is the number of names defined at the point of the label.
void
-Bindings_snapshot::check_goto_defs(source_location loc, const Block* block,
+Bindings_snapshot::check_goto_defs(Location loc, const Block* block,
size_t cfrom, size_t cto)
{
if (cfrom < cto)
Variable::Variable(Type* type, Expression* init, bool is_global,
bool is_parameter, bool is_receiver,
- source_location location)
+ Location location)
: type_(type), init_(init), preinit_(NULL), location_(location),
backend_(NULL), is_global_(is_global), is_parameter_(is_parameter),
is_receiver_(is_receiver), is_varargs_parameter_(false),
Named_object*
Type_declaration::add_method_declaration(const std::string& name,
Function_type* type,
- source_location location)
+ Location location)
{
Named_object* ret = Named_object::make_function_declaration(name, NULL, type,
location);
Named_object*
Named_object::make_unknown_name(const std::string& name,
- source_location location)
+ Location location)
{
Named_object* named_object = new Named_object(name, NULL,
NAMED_OBJECT_UNKNOWN);
Named_object*
Named_object::make_type(const std::string& name, const Package* package,
- Type* type, source_location location)
+ Type* type, Location location)
{
Named_object* named_object = new Named_object(name, package,
NAMED_OBJECT_TYPE);
Named_object*
Named_object::make_type_declaration(const std::string& name,
const Package* package,
- source_location location)
+ Location location)
{
Named_object* named_object = new Named_object(name, package,
NAMED_OBJECT_TYPE_DECLARATION);
Named_object::make_function_declaration(const std::string& name,
const Package* package,
Function_type* fntype,
- source_location location)
+ Location location)
{
Named_object* named_object = new Named_object(name, package,
NAMED_OBJECT_FUNC_DECLARATION);
// Return the location of a named object.
-source_location
+Location
Named_object::location() const
{
switch (this->classification_)
Bindings::add_function_declaration(const std::string& name,
const Package* package,
Function_type* type,
- source_location location)
+ Location location)
{
Named_object* no = Named_object::make_function_declaration(name, package,
type, location);
// Return an expression for the address of this label.
Bexpression*
-Label::get_addr(Translate_context* context, source_location location)
+Label::get_addr(Translate_context* context, Location location)
{
Blabel* label = this->get_backend_label(context);
return context->backend()->label_address(label, location);
// Return a goto statement to this unnamed label.
Bstatement*
-Unnamed_label::get_goto(Translate_context* context, source_location location)
+Unnamed_label::get_goto(Translate_context* context, Location location)
{
Blabel* blabel = this->get_blabel(context);
return context->backend()->goto_statement(blabel, location);
// Class Package.
Package::Package(const std::string& name, const std::string& unique_prefix,
- source_location location)
+ Location location)
: name_(name), unique_prefix_(unique_prefix), bindings_(new Bindings(NULL)),
priority_(0), location_(location), used_(false), is_imported_(false),
uses_sink_alias_(false)
#ifndef GO_GOGO_H
#define GO_GOGO_H
+#include "go-linemap.h"
+
class Traverse;
class Statement_inserter;
class Type;
public:
// Create the IR, passing in the sizes of the types "int" and
// "uintptr" in bits.
- Gogo(Backend* backend, int int_type_size, int pointer_size);
+ Gogo(Backend* backend, Linemap *linemap, int int_type_size, int pointer_size);
// Get the backend generator.
Backend*
backend()
{ return this->backend_; }
+ // Get the Location generator.
+ Linemap*
+ linemap()
+ { return this->linemap_; }
+
// Get the package name.
const std::string&
package_name() const;
// Set the package name.
void
- set_package_name(const std::string&, source_location);
+ set_package_name(const std::string&, Location);
// Return whether this is the "main" package.
bool
// the declarations are added to the global scope.
void
import_package(const std::string& filename, const std::string& local_name,
- bool is_local_name_exported, source_location);
+ bool is_local_name_exported, Location);
// Whether we are the global binding level.
bool
add_imported_package(const std::string& real_name, const std::string& alias,
bool is_alias_exported,
const std::string& unique_prefix,
- source_location location,
+ Location location,
bool* padd_to_globals);
// Register a package. This package may or may not be imported.
// it necessary.
Package*
register_package(const std::string& name, const std::string& unique_prefix,
- source_location);
+ Location);
// Start compiling a function. ADD_METHOD_TO_TYPE is true if a
// method function should be added to the type of its receiver.
Named_object*
start_function(const std::string& name, Function_type* type,
- bool add_method_to_type, source_location);
+ bool add_method_to_type, Location);
// Finish compiling a function.
void
- finish_function(source_location);
+ finish_function(Location);
// Return the current function.
Named_object*
// Start a new block. This is not initially associated with a
// function.
void
- start_block(source_location);
+ start_block(Location);
// Finish the current block and return it.
Block*
- finish_block(source_location);
+ finish_block(Location);
// Declare an unknown name. This is used while parsing. The name
// must be resolved by the end of the parse. Unknown names are
// always added at the package level.
Named_object*
- add_unknown_name(const std::string& name, source_location);
+ add_unknown_name(const std::string& name, Location);
// Declare a function.
Named_object*
- declare_function(const std::string&, Function_type*, source_location);
+ declare_function(const std::string&, Function_type*, Location);
// Add a label.
Label*
- add_label_definition(const std::string&, source_location);
+ add_label_definition(const std::string&, Location);
// Add a label reference. ISSUE_GOTO_ERRORS is true if we should
// report errors for a goto from the current location to the label
// location.
Label*
- add_label_reference(const std::string&, source_location,
+ add_label_reference(const std::string&, Location,
bool issue_goto_errors);
// Return a snapshot of the current binding state.
Bindings_snapshot*
- bindings_snapshot(source_location);
+ bindings_snapshot(Location);
// Add a statement to the current block.
void
// Add a block to the current block.
void
- add_block(Block*, source_location);
+ add_block(Block*, Location);
// Add a constant.
Named_object*
// Add a type.
void
- add_type(const std::string&, Type*, source_location);
+ add_type(const std::string&, Type*, Location);
// Add a named type. This is used for builtin types, and to add an
// imported type to the global scope.
// Declare a type.
Named_object*
- declare_type(const std::string&, source_location);
+ declare_type(const std::string&, Location);
// Declare a type at the package level. This is used when the
// parser sees an unknown name where a type name is required.
Named_object*
- declare_package_type(const std::string&, source_location);
+ declare_package_type(const std::string&, Location);
// Define a type which was already declared.
void
// RETTYPE is the return type. It is followed by NARGS pairs of
// type and argument (both trees).
static tree
- call_builtin(tree* pdecl, source_location, const char* name, int nargs,
+ call_builtin(tree* pdecl, Location, const char* name, int nargs,
tree rettype, ...);
// Build a call to the runtime error function.
static tree
- runtime_error(int code, source_location);
+ runtime_error(int code, Location);
// Build a builtin struct with a list of fields.
static tree
// Return a tree which allocate SIZE bytes to hold values of type
// TYPE.
tree
- allocate_memory(Type *type, tree size, source_location);
+ allocate_memory(Type *type, tree size, Location);
// Return a type to use for pointer to const char.
static tree
// Receive a value from a channel.
static tree
receive_from_channel(tree type_tree, tree channel, bool for_select,
- source_location);
+ Location);
// Return a tree for receiving an integer on a channel.
static tree
// Make a trampoline which calls FNADDR passing CLOSURE.
tree
- make_trampoline(tree fnaddr, tree closure, source_location);
+ make_trampoline(tree fnaddr, tree closure, Location);
private:
// During parsing, we keep a stack of functions. Each function on
// Set up the built-in unsafe package.
void
- import_unsafe(const std::string&, bool is_exported, source_location);
+ import_unsafe(const std::string&, bool is_exported, Location);
// Add a new imported package.
Named_object*
add_package(const std::string& real_name, const std::string& alias,
- const std::string& unique_prefix, source_location location);
+ const std::string& unique_prefix, Location location);
// Return the current binding contour.
Bindings*
// The backend generator.
Backend* backend_;
+ // The object used to keep track of file names and line numbers.
+ Linemap* linemap_;
// The package we are compiling.
Package* package_;
// The list of currently open functions during parsing.
class Block
{
public:
- Block(Block* enclosing, source_location);
+ Block(Block* enclosing, Location);
// Return the enclosing block.
const Block*
// Return the start location. This is normally the location of the
// left curly brace which starts the block.
- source_location
+ Location
start_location() const
{ return this->start_location_; }
// Return the end location. This is normally the location of the
// right curly brace which ends the block.
- source_location
+ Location
end_location() const
{ return this->end_location_; }
// Set the end location of the block.
void
- set_end_location(source_location location)
+ set_end_location(Location location)
{ this->end_location_ = location; }
// Traverse the tree.
// Binding contour.
Bindings* bindings_;
// Location of start of block.
- source_location start_location_;
+ Location start_location_;
// Location of end of block.
- source_location end_location_;
+ Location end_location_;
};
// A function.
class Function
{
public:
- Function(Function_type* type, Function*, Block*, source_location);
+ Function(Function_type* type, Function*, Block*, Location);
// Return the function's type.
Function_type*
// Add a new field to the closure variable.
void
- add_closure_field(Named_object* var, source_location loc)
+ add_closure_field(Named_object* var, Location loc)
{ this->closure_fields_.push_back(std::make_pair(var, loc)); }
// Whether this function needs a closure.
{ return this->block_; }
// Get the location of the start of the function.
- source_location
+ Location
location() const
{ return this->location_; }
// Add a label definition to the function.
Label*
- add_label_definition(Gogo*, const std::string& label_name, source_location);
+ add_label_definition(Gogo*, const std::string& label_name, Location);
// Add a label reference to a function. ISSUE_GOTO_ERRORS is true
// if we should report errors for a goto from the current location
// to the label location.
Label*
add_label_reference(Gogo*, const std::string& label_name,
- source_location, bool issue_goto_errors);
+ Location, bool issue_goto_errors);
// Warn about labels that are defined but not used.
void
// Get the value to return when not explicitly specified. May also
// add statements to execute first to STMT_LIST.
tree
- return_value(Gogo*, Named_object*, source_location, tree* stmt_list) const;
+ return_value(Gogo*, Named_object*, Location, tree* stmt_list) const;
// Get a tree for the variable holding the defer stack.
Expression*
- defer_stack(source_location);
+ defer_stack(Location);
// Export the function.
void
build_defer_wrapper(Gogo*, Named_object*, tree*, tree*);
typedef std::vector<std::pair<Named_object*,
- source_location> > Closure_fields;
+ Location> > Closure_fields;
// The function's type.
Function_type* type_;
// The outer block of statements in the function.
Block* block_;
// The source location of the start of the function.
- source_location location_;
+ Location location_;
// Labels defined or referenced in the function.
Labels labels_;
// The function decl.
class Bindings_snapshot
{
public:
- Bindings_snapshot(const Block*, source_location);
+ Bindings_snapshot(const Block*, Location);
// Report any errors appropriate for a goto from the current binding
// state of B to this one.
void
- check_goto_from(const Block* b, source_location);
+ check_goto_from(const Block* b, Location);
// Report any errors appropriate for a goto from this binding state
// to the current state of B.
private:
bool
- check_goto_block(source_location, const Block*, const Block*, size_t*);
+ check_goto_block(Location, const Block*, const Block*, size_t*);
void
- check_goto_defs(source_location, const Block*, size_t, size_t);
+ check_goto_defs(Location, const Block*, size_t, size_t);
// The current block.
const Block* block_;
// this->block_->enclosing(), etc.
std::vector<size_t> counts_;
// The location where this snapshot was taken.
- source_location location_;
+ Location location_;
};
// A function declaration.
class Function_declaration
{
public:
- Function_declaration(Function_type* fntype, source_location location)
+ Function_declaration(Function_type* fntype, Location location)
: fntype_(fntype), location_(location), asm_name_(), fndecl_(NULL)
{ }
type() const
{ return this->fntype_; }
- source_location
+ Location
location() const
{ return this->location_; }
// The type of the function.
Function_type* fntype_;
// The location of the declaration.
- source_location location_;
+ Location location_;
// The assembler name: this is the name to use in references to the
// function. This is normally empty.
std::string asm_name_;
{
public:
Variable(Type*, Expression*, bool is_global, bool is_parameter,
- bool is_receiver, source_location);
+ bool is_receiver, Location);
// Get the type of the variable.
Type*
{ this->is_non_escaping_address_taken_ = true; }
// Get the source location of the variable's declaration.
- source_location
+ Location
location() const
{ return this->location_; }
// Statements to run before the init statement.
Block* preinit_;
// Location of variable definition.
- source_location location_;
+ Location location_;
// Backend representation.
Bvariable* backend_;
// Whether this is a global variable.
{
public:
Result_variable(Type* type, Function* function, int index,
- source_location location)
+ Location location)
: type_(type), function_(function), index_(index), location_(location),
backend_(NULL), is_address_taken_(false),
is_non_escaping_address_taken_(false)
{ return this->index_; }
// The location of the variable definition.
- source_location
+ Location
location() const
{ return this->location_; }
// Index in list of results.
int index_;
// Where the result variable is defined.
- source_location location_;
+ Location location_;
// Backend representation.
Bvariable* backend_;
// Whether something takes the address of this variable.
{
public:
Named_constant(Type* type, Expression* expr, int iota_value,
- source_location location)
+ Location location)
: type_(type), expr_(expr), iota_value_(iota_value), location_(location),
lowering_(false)
{ }
iota_value() const
{ return this->iota_value_; }
- source_location
+ Location
location() const
{ return this->location_; }
// we lower.
int iota_value_;
// The location of the definition.
- source_location location_;
+ Location location_;
// Whether we are currently lowering this constant.
bool lowering_;
};
class Type_declaration
{
public:
- Type_declaration(source_location location)
+ Type_declaration(Location location)
: location_(location), in_function_(NULL), methods_(),
issued_warning_(false)
{ }
// Return the location.
- source_location
+ Location
location() const
{ return this->location_; }
// Add a method declaration to this type.
Named_object*
add_method_declaration(const std::string& name, Function_type* type,
- source_location location);
+ Location location);
// Return whether any methods were defined.
bool
typedef std::vector<Named_object*> Methods;
// The location of the type declaration.
- source_location location_;
+ Location location_;
// If this type is declared in a function, a pointer back to the
// function in which it is defined.
Named_object* in_function_;
class Unknown_name
{
public:
- Unknown_name(source_location location)
+ Unknown_name(Location location)
: location_(location), real_named_object_(NULL)
{ }
// Return the location where this name was first seen.
- source_location
+ Location
location() const
{ return this->location_; }
private:
// The location where this name was first seen.
- source_location location_;
+ Location location_;
// The real named object when it is known.
Named_object*
real_named_object_;
// Creators.
static Named_object*
- make_unknown_name(const std::string& name, source_location);
+ make_unknown_name(const std::string& name, Location);
static Named_object*
make_constant(const Typed_identifier&, const Package*, Expression*,
int iota_value);
static Named_object*
- make_type(const std::string&, const Package*, Type*, source_location);
+ make_type(const std::string&, const Package*, Type*, Location);
static Named_object*
- make_type_declaration(const std::string&, const Package*, source_location);
+ make_type_declaration(const std::string&, const Package*, Location);
static Named_object*
make_variable(const std::string&, const Package*, Variable*);
static Named_object*
make_function_declaration(const std::string&, const Package*, Function_type*,
- source_location);
+ Location);
static Named_object*
make_package(const std::string& alias, Package* package);
}
// The location where this object was defined or referenced.
- source_location
+ Location
location() const;
// Convert a variable to the backend representation.
// Add an unknown name.
Named_object*
- add_unknown_name(const std::string& name, source_location location)
+ add_unknown_name(const std::string& name, Location location)
{
return this->add_named_object(Named_object::make_unknown_name(name,
location));
// Add a type.
Named_object*
add_type(const std::string& name, const Package* package, Type* type,
- source_location location)
+ Location location)
{
return this->add_named_object(Named_object::make_type(name, package, type,
location));
// Add a type declaration.
Named_object*
add_type_declaration(const std::string& name, const Package* package,
- source_location location)
+ Location location)
{
Named_object* no = Named_object::make_type_declaration(name, package,
location);
// Add a function declaration.
Named_object*
add_function_declaration(const std::string& name, const Package* package,
- Function_type* type, source_location location);
+ Function_type* type, Location location);
// Add a package. The location is the location of the import
// statement.
{
public:
Label(const std::string& name)
- : name_(name), location_(0), snapshot_(NULL), refs_(), is_used_(false),
- blabel_(NULL)
+ : name_(name), location_(Linemap::unknown_location()), snapshot_(NULL),
+ refs_(), is_used_(false), blabel_(NULL)
{ }
// Return the label's name.
// Return whether the label has been defined.
bool
is_defined() const
- { return this->location_ != 0; }
+ { return !Linemap::is_unknown_location(this->location_); }
// Return whether the label has been used.
bool
{ this->is_used_ = true; }
// Return the location of the definition.
- source_location
+ Location
location() const
{ return this->location_; }
void
add_snapshot_ref(Bindings_snapshot* snapshot)
{
- go_assert(this->location_ == 0);
+ go_assert(Linemap::is_unknown_location(this->location_));
this->refs_.push_back(snapshot);
}
// Define the label at LOCATION with the given bindings snapshot.
void
- define(source_location location, Bindings_snapshot* snapshot)
+ define(Location location, Bindings_snapshot* snapshot)
{
- go_assert(this->location_ == 0 && this->snapshot_ == NULL);
+ go_assert(Linemap::is_unknown_location(this->location_)
+ && this->snapshot_ == NULL);
this->location_ = location;
this->snapshot_ = snapshot;
}
// to get the return address of a deferred function to see whether
// the function may call recover.
Bexpression*
- get_addr(Translate_context*, source_location location);
+ get_addr(Translate_context*, Location location);
private:
// The name of the label.
std::string name_;
// The location of the definition. This is 0 if the label has not
// yet been defined.
- source_location location_;
+ Location location_;
// A snapshot of the set of bindings defined at this label, used to
// issue errors about invalid goto statements.
Bindings_snapshot* snapshot_;
class Unnamed_label
{
public:
- Unnamed_label(source_location location)
+ Unnamed_label(Location location)
: location_(location), blabel_(NULL)
{ }
// Get the location where the label is defined.
- source_location
+ Location
location() const
{ return this->location_; }
// Set the location where the label is defined.
void
- set_location(source_location location)
+ set_location(Location location)
{ this->location_ = location; }
// Return a statement which defines this label.
// Return a goto to this label from LOCATION.
Bstatement*
- get_goto(Translate_context*, source_location location);
+ get_goto(Translate_context*, Location location);
private:
// Return the backend representation.
get_blabel(Translate_context*);
// The location where the label is defined.
- source_location location_;
+ Location location_;
// The backend representation of this label.
Blabel* blabel_;
};
{
public:
Package(const std::string& name, const std::string& unique_prefix,
- source_location location);
+ Location location);
// The real name of this package. This may be different from the
// name in the associated Named_object if the import statement used
{ return this->name_; }
// Return the location of the import statement.
- source_location
+ Location
location() const
{ return this->location_; }
// Set the location of the package. This is used if it is seen in a
// different import before it is really imported.
void
- set_location(source_location location)
+ set_location(Location location)
{ this->location_ = location; }
// Add a constant to the package.
// Add a type to the package.
Named_object*
- add_type(const std::string& name, Type* type, source_location location)
+ add_type(const std::string& name, Type* type, Location location)
{ return this->bindings_->add_type(name, this, type, location); }
// Add a type declaration to the package.
Named_object*
- add_type_declaration(const std::string& name, source_location location)
+ add_type_declaration(const std::string& name, Location location)
{ return this->bindings_->add_type_declaration(name, this, location); }
// Add a variable to the package.
// Add a function declaration to the package.
Named_object*
add_function_declaration(const std::string& name, Function_type* type,
- source_location loc)
+ Location loc)
{ return this->bindings_->add_function_declaration(name, this, type, loc); }
// Determine types of constants.
// is used to run init functions in the right order.
int priority_;
// The location of the import statement.
- source_location location_;
+ Location location_;
// True if some name from this package was used. This is mutable
// because we can use a package even if we have a const pointer to
// it.
class Archive_file
{
public:
- Archive_file(const std::string& filename, int fd, source_location location)
+ Archive_file(const std::string& filename, int fd, Location location)
: filename_(filename), fd_(fd), filesize_(-1), extended_names_(),
is_thin_archive_(false), location_(location), nested_archives_()
{ }
{ return this->is_thin_archive_; }
// Return the location of the import statement.
- source_location
+ Location
location() const
{ return this->location_; }
// Whether this is a thin archive.
bool is_thin_archive_;
// The location of the import statements.
- source_location location_;
+ Location location_;
// Table of nested archives.
Nested_archive_table nested_archives_;
};
Import::Stream*
Import::find_archive_export_data(const std::string& filename, int fd,
- source_location location)
+ Location location)
{
Archive_file afile(filename, fd, location);
if (!afile.initialize())
// later in the search path.
Import::Stream*
-Import::open_package(const std::string& filename, source_location location)
+Import::open_package(const std::string& filename, Location location)
{
if (!IS_ABSOLUTE_PATH(filename))
{
Import::Stream*
Import::try_package_in_directory(const std::string& filename,
- source_location location)
+ Location location)
{
std::string found_filename = filename;
int fd = open(found_filename.c_str(), O_RDONLY | O_BINARY);
Import::Stream*
Import::find_export_data(const std::string& filename, int fd,
- source_location location)
+ Location location)
{
// See if we can read this as an object file.
Import::Stream* stream = Import::find_object_export_data(filename, fd, 0,
Import::find_object_export_data(const std::string& filename,
int fd,
off_t offset,
- source_location location)
+ Location location)
{
const char* errmsg;
int err;
// Construct an Import object. We make the builtin_types_ vector
// large enough to hold all the builtin types.
-Import::Import(Stream* stream, source_location location)
+Import::Import(Stream* stream, Location location)
: gogo_(NULL), stream_(stream), location_(location), package_(NULL),
add_to_globals_(false),
builtin_types_((- SMALLEST_BUILTIN_CODE) + 1),
if (is_varargs)
fntype->set_is_varargs();
- source_location loc = this->location_;
+ Location loc = this->location_;
Named_object* no;
if (fntype->is_method())
{
package = this->package_;
else
package = this->gogo_->register_package(package_name, unique_prefix,
- UNKNOWN_LOCATION);
+ Linemap::unknown_location());
Named_object* no = package->bindings()->lookup(type_name);
if (no == NULL)
// Require that the next LENGTH bytes from the stream match BYTES.
void
-Import::Stream::require_bytes(source_location location, const char* bytes,
+Import::Stream::require_bytes(Location location, const char* bytes,
size_t length)
{
const char* read;
#define GO_IMPORT_H
#include "export.h"
+#include "go-linemap.h"
class Gogo;
class Package;
// Give an error if the next bytes do not match STR. Advance the
// read position by the length of STR.
void
- require_c_string(source_location location, const char* str)
+ require_c_string(Location location, const char* str)
{ this->require_bytes(location, str, strlen(str)); }
// Given an error if the next LENGTH bytes do not match BYTES.
// Advance the read position by LENGTH.
void
- require_bytes(source_location, const char* bytes, size_t length);
+ require_bytes(Location, const char* bytes, size_t length);
// Advance the read position by SKIP bytes.
void
// returns a pointer to a Stream object to read the data that it
// exports. LOCATION is the location of the import statement.
static Stream*
- open_package(const std::string& filename, source_location location);
+ open_package(const std::string& filename, Location location);
// Constructor.
- Import(Stream*, source_location);
+ Import(Stream*, Location);
// Register the builtin types.
void
import(Gogo*, const std::string& local_name, bool is_local_name_exported);
// The location of the import statement.
- source_location
+ Location
location() const
{ return this->location_; }
private:
static Stream*
- try_package_in_directory(const std::string&, source_location);
+ try_package_in_directory(const std::string&, Location);
static int
try_suffixes(std::string*);
static Stream*
- find_export_data(const std::string& filename, int fd, source_location);
+ find_export_data(const std::string& filename, int fd, Location);
static Stream*
find_object_export_data(const std::string& filename, int fd,
- off_t offset, source_location);
+ off_t offset, Location);
static const int archive_magic_len = 8;
static Stream*
find_archive_export_data(const std::string& filename, int fd,
- source_location);
+ Location);
// Read the import control functions.
void
// The stream from which to read import data.
Stream* stream_;
// The location of the import statement we are processing.
- source_location location_;
+ Location location_;
// The package we are importing.
Package* package_;
// Whether to add new objects to the global scope, rather than to a
// Make a general token.
-Token::Token(Classification classification, source_location location)
+Token::Token(Classification classification, Location location)
: classification_(classification), location_(location)
{
}
// Class Lex.
-Lex::Lex(const char* input_file_name, FILE* input_file)
+Lex::Lex(const char* input_file_name, FILE* input_file, Linemap* linemap)
: input_file_name_(input_file_name), input_file_(input_file),
- linebuf_(NULL), linebufsize_(120), linesize_(0), lineoff_(0),
- lineno_(0), add_semi_at_eol_(false)
+ linemap_(linemap), linebuf_(NULL), linebufsize_(120), linesize_(0),
+ lineoff_(0), lineno_(0), add_semi_at_eol_(false)
{
this->linebuf_ = new char[this->linebufsize_];
- linemap_add(line_table, LC_ENTER, 0, input_file_name, 1);
+ this->linemap_->start_file(input_file_name, 0);
}
Lex::~Lex()
{
delete[] this->linebuf_;
- linemap_add(line_table, LC_LEAVE, 0, NULL, 0);
}
// Read a new line from the file.
this->linesize_= got;
this->lineoff_ = 0;
- linemap_line_start(line_table, this->lineno_, this->linesize_);
+ this->linemap_->start_line(this->lineno_, this->linesize_);
return true;
}
// Get the current location.
-source_location
+Location
Lex::location() const
{
- return linemap_position_for_column (line_table, this->lineoff_ + 1);
+ return this->linemap_->get_location(this->lineoff_ + 1);
}
// Get a location slightly before the current one. This is used for
// slightly more efficient handling of operator tokens.
-source_location
+Location
Lex::earlier_location(int chars) const
{
- return linemap_position_for_column (line_table, this->lineoff_ + 1 - chars);
+ return this->linemap_->get_location(this->lineoff_ + 1 - chars);
}
// Get the next token.
else if (p[1] == '*')
{
this->lineoff_ = p - this->linebuf_;
- source_location location = this->location();
+ Location location = this->location();
if (!this->skip_c_comment())
return Token::make_invalid_token(location);
p = this->linebuf_ + this->lineoff_;
buf.append(ubuf);
}
}
- source_location location = this->location();
+ Location location = this->location();
this->add_semi_at_eol_ = true;
this->lineoff_ = p - this->linebuf_;
if (has_non_ascii_char)
const char* p = pstart;
const char* pend = this->linebuf_ + this->linesize_;
- source_location location = this->location();
+ Location location = this->location();
bool neg = false;
if (*p == '+')
void
Lex::append_char(unsigned int v, bool is_character, std::string* str,
- source_location location)
+ Location location)
{
char buf[4];
size_t len;
mpz_t val;
mpz_init_set_ui(val, value);
- source_location location = this->location();
+ Location location = this->location();
this->lineoff_ = p + 1 - this->linebuf_;
Token ret = Token::make_integer_token(val, location);
mpz_clear(val);
std::string value;
while (*p != '"')
{
- source_location loc = this->location();
+ Location loc = this->location();
unsigned int c;
bool is_character;
this->lineoff_ = p - this->linebuf_;
Lex::append_char(c, is_character, &value, loc);
}
- source_location location = this->location();
+ Location location = this->location();
this->lineoff_ = p + 1 - this->linebuf_;
return Token::make_string_token(value, location);
}
{
const char* p = this->linebuf_ + this->lineoff_ + 1;
const char* pend = this->linebuf_ + this->linesize_;
- source_location location = this->location();
+ Location location = this->location();
std::string value;
while (true)
this->lineoff_ = p + 1 - this->linebuf_;
return Token::make_string_token(value, location);
}
- source_location loc = this->location();
+ Location loc = this->location();
unsigned int c;
bool issued_error;
this->lineoff_ = p - this->linebuf_;
memcpy(file, p, filelen);
file[filelen] = '\0';
- linemap_add(line_table, LC_LEAVE, 0, NULL, 0);
- linemap_add(line_table, LC_ENTER, 0, file, lineno);
+ this->linemap_->start_file(file, lineno);
this->lineno_ = lineno - 1;
p = plend;
#include <mpfr.h>
#include "operator.h"
+#include "go-linemap.h"
struct Unicode_range;
// Make a token for an invalid value.
static Token
- make_invalid_token(source_location location)
+ make_invalid_token(Location location)
{ return Token(TOKEN_INVALID, location); }
// Make a token representing end of file.
static Token
- make_eof_token(source_location location)
+ make_eof_token(Location location)
{ return Token(TOKEN_EOF, location); }
// Make a keyword token.
static Token
- make_keyword_token(Keyword keyword, source_location location)
+ make_keyword_token(Keyword keyword, Location location)
{
Token tok(TOKEN_KEYWORD, location);
tok.u_.keyword = keyword;
// Make an identifier token.
static Token
make_identifier_token(const std::string& value, bool is_exported,
- source_location location)
+ Location location)
{
Token tok(TOKEN_IDENTIFIER, location);
tok.u_.identifier_value.name = new std::string(value);
// Make a quoted string token.
static Token
- make_string_token(const std::string& value, source_location location)
+ make_string_token(const std::string& value, Location location)
{
Token tok(TOKEN_STRING, location);
tok.u_.string_value = new std::string(value);
// Make an operator token.
static Token
- make_operator_token(Operator op, source_location location)
+ make_operator_token(Operator op, Location location)
{
Token tok(TOKEN_OPERATOR, location);
tok.u_.op = op;
// Make an integer token.
static Token
- make_integer_token(mpz_t val, source_location location)
+ make_integer_token(mpz_t val, Location location)
{
Token tok(TOKEN_INTEGER, location);
mpz_init(tok.u_.integer_value);
// Make a float token.
static Token
- make_float_token(mpfr_t val, source_location location)
+ make_float_token(mpfr_t val, Location location)
{
Token tok(TOKEN_FLOAT, location);
mpfr_init(tok.u_.float_value);
// Make a token for an imaginary number.
static Token
- make_imaginary_token(mpfr_t val, source_location location)
+ make_imaginary_token(mpfr_t val, Location location)
{
Token tok(TOKEN_IMAGINARY, location);
mpfr_init(tok.u_.float_value);
}
// Get the location of the token.
- source_location
+ Location
location() const
{ return this->location_; }
private:
// Private constructor used by make_..._token functions above.
- Token(Classification, source_location);
+ Token(Classification, Location);
// Clear the token.
void
Operator op;
} u_;
// The source location.
- source_location location_;
+ Location location_;
};
// The lexer itself.
class Lex
{
public:
- Lex(const char* input_file_name, FILE* input_file);
+ Lex(const char* input_file_name, FILE* input_file, Linemap *linemap);
~Lex();
// location is used to warn about an out of range character.
static void
append_char(unsigned int v, bool is_charater, std::string* str,
- source_location);
+ Location);
// A helper function. Fetch a UTF-8 character from STR and store it
// in *VALUE. Return the number of bytes read from STR. Return 0
require_line();
// The current location.
- source_location
+ Location
location() const;
// A position CHARS column positions before the current location.
- source_location
+ Location
earlier_location(int chars) const;
static bool
const char* input_file_name_;
// The input file.
FILE* input_file_;
+ // The object used to keep track of file names and line numbers.
+ Linemap* linemap_;
// The line buffer. This holds the current line.
char* linebuf_;
// The size of the line buffer.
Parse::Parse(Lex* lex, Gogo* gogo)
: lex_(lex),
- token_(Token::make_invalid_token(0)),
- unget_token_(Token::make_invalid_token(0)),
+ token_(Token::make_invalid_token(Linemap::unknown_location())),
+ unget_token_(Token::make_invalid_token(Linemap::unknown_location())),
unget_token_valid_(false),
gogo_(gogo),
break_stack_(NULL),
// The location of the current token.
-source_location
+Location
Parse::location()
{
return this->peek_token()->location();
return ret;
// Most expression lists permit a trailing comma.
- source_location location = token->location();
+ Location location = token->location();
this->advance_token();
if (!this->expression_may_start_here())
{
return this->interface_type();
else if (token->is_keyword(KEYWORD_FUNC))
{
- source_location location = token->location();
+ Location location = token->location();
this->advance_token();
Type* type = this->signature(NULL, location);
if (type == NULL)
Type*
Parse::type_name(bool issue_error)
{
- source_location location = this->location();
+ Location location = this->location();
std::string name;
Named_object* package;
Type*
Parse::map_type()
{
- source_location location = this->location();
+ Location location = this->location();
go_assert(this->peek_token()->is_keyword(KEYWORD_MAP));
if (!this->advance_token()->is_op(OPERATOR_LSQUARE))
{
Parse::struct_type()
{
go_assert(this->peek_token()->is_keyword(KEYWORD_STRUCT));
- source_location location = this->location();
+ Location location = this->location();
if (!this->advance_token()->is_op(OPERATOR_LCURLY))
{
- source_location token_loc = this->location();
+ Location token_loc = this->location();
if (this->peek_token()->is_op(OPERATOR_SEMICOLON)
&& this->advance_token()->is_op(OPERATOR_LCURLY))
error_at(token_loc, "unexpected semicolon or newline before %<{%>");
Parse::field_decl(Struct_field_list* sfl)
{
const Token* token = this->peek_token();
- source_location location = token->location();
+ Location location = token->location();
bool is_anonymous;
bool is_anonymous_pointer;
if (token->is_op(OPERATOR_MULT))
{
std::string id = token->identifier();
bool is_id_exported = token->is_identifier_exported();
- source_location id_location = token->location();
+ Location id_location = token->location();
token = this->advance_token();
is_anonymous = (token->is_op(OPERATOR_SEMICOLON)
|| token->is_op(OPERATOR_RCURLY)
// This returns NULL on a parse error.
Function_type*
-Parse::signature(Typed_identifier* receiver, source_location location)
+Parse::signature(Typed_identifier* receiver, Location location)
{
bool is_varargs = false;
Typed_identifier_list* params;
Typed_identifier_list*
Parse::parameter_list(bool* is_varargs)
{
- source_location location = this->location();
+ Location location = this->location();
Typed_identifier_list* ret = new Typed_identifier_list();
bool saw_error = false;
{
std::string name = token->identifier();
bool is_exported = token->is_identifier_exported();
- source_location location = token->location();
+ Location location = token->location();
token = this->advance_token();
if (!token->is_op(OPERATOR_COMMA))
{
if (!parameters_have_names)
{
Type* type;
- source_location location = this->location();
+ Location location = this->location();
if (!this->peek_token()->is_identifier())
{
if (!this->peek_token()->is_op(OPERATOR_ELLIPSIS))
return this->parameters(presults, NULL);
else
{
- source_location location = this->location();
+ Location location = this->location();
Type* type = this->type();
if (type->is_error_type())
{
// Returns the location of the closing brace.
-source_location
+Location
Parse::block()
{
if (!this->peek_token()->is_op(OPERATOR_LCURLY))
{
- source_location loc = this->location();
+ Location loc = this->location();
if (this->peek_token()->is_op(OPERATOR_SEMICOLON)
&& this->advance_token()->is_op(OPERATOR_LCURLY))
error_at(loc, "unexpected semicolon or newline before %<{%>");
else
{
error_at(this->location(), "expected %<{%>");
- return UNKNOWN_LOCATION;
+ return Linemap::unknown_location();
}
}
// Skip ahead to the end of the block, in hopes of avoiding
// lots of meaningless errors.
- source_location ret = token->location();
+ Location ret = token->location();
int nest = 0;
while (!token->is_eof())
{
}
}
- source_location ret = token->location();
+ Location ret = token->location();
this->advance_token();
return ret;
}
Parse::interface_type()
{
go_assert(this->peek_token()->is_keyword(KEYWORD_INTERFACE));
- source_location location = this->location();
+ Location location = this->location();
if (!this->advance_token()->is_op(OPERATOR_LCURLY))
{
- source_location token_loc = this->location();
+ Location token_loc = this->location();
if (this->peek_token()->is_op(OPERATOR_SEMICOLON)
&& this->advance_token()->is_op(OPERATOR_LCURLY))
error_at(token_loc, "unexpected semicolon or newline before %<{%>");
std::string name = token->identifier();
bool is_exported = token->is_identifier_exported();
- source_location location = token->location();
+ Location location = token->location();
if (this->advance_token()->is_op(OPERATOR_LPAREN))
{
}
std::string name = token->identifier();
bool is_exported = token->is_identifier_exported();
- source_location location = token->location();
+ Location location = token->location();
token = this->advance_token();
// The scope of the type name starts at the point where the
Typed_identifier_list til;
this->identifier_list(&til);
- source_location location = this->location();
+ Location location = this->location();
Type* type = NULL;
Expression_list* init = NULL;
void
Parse::init_vars(const Typed_identifier_list* til, Type* type,
Expression_list* init, bool is_coloneq,
- source_location location)
+ Location location)
{
// Check for an initialization which can yield multiple values.
if (init != NULL && init->size() == 1 && til->size() > 1)
bool
Parse::init_vars_from_call(const Typed_identifier_list* vars, Type* type,
Expression* expr, bool is_coloneq,
- source_location location)
+ Location location)
{
Call_expression* call = expr->call_expression();
if (call == NULL)
bool
Parse::init_vars_from_map(const Typed_identifier_list* vars, Type* type,
Expression* expr, bool is_coloneq,
- source_location location)
+ Location location)
{
Index_expression* index = expr->index_expression();
if (index == NULL)
bool
Parse::init_vars_from_receive(const Typed_identifier_list* vars, Type* type,
Expression* expr, bool is_coloneq,
- source_location location)
+ Location location)
{
Receive_expression* receive = expr->receive_expression();
if (receive == NULL)
bool
Parse::init_vars_from_type_guard(const Typed_identifier_list* vars,
Type* type, Expression* expr,
- bool is_coloneq, source_location location)
+ bool is_coloneq, Location location)
{
Type_guard_expression* type_guard = expr->type_guard_expression();
if (type_guard == NULL)
Parse::init_var(const Typed_identifier& tid, Type* type, Expression* init,
bool is_coloneq, bool type_from_init, bool* is_new)
{
- source_location location = tid.location();
+ Location location = tid.location();
if (Gogo::is_sink_name(tid.name()))
{
Named_object*
Parse::create_dummy_global(Type* type, Expression* init,
- source_location location)
+ Location location)
{
if (type == NULL && init == NULL)
type = Type::lookup_bool_type();
void
Parse::simple_var_decl_or_assignment(const std::string& name,
- source_location location,
+ Location location,
Range_clause* p_range_clause,
Type_switch* p_type_switch)
{
std::string id = token->identifier();
bool is_id_exported = token->is_identifier_exported();
- source_location id_location = token->location();
+ Location id_location = token->location();
token = this->advance_token();
if (!token->is_op(OPERATOR_COMMA))
Parse::function_decl()
{
go_assert(this->peek_token()->is_keyword(KEYWORD_FUNC));
- source_location location = this->location();
+ Location location = this->location();
const Token* token = this->advance_token();
Typed_identifier* rec = NULL;
// Check for the easy error of a newline before the opening brace.
if (this->peek_token()->is_op(OPERATOR_SEMICOLON))
{
- source_location semi_loc = this->location();
+ Location semi_loc = this->location();
if (this->advance_token()->is_op(OPERATOR_LCURLY))
error_at(this->location(),
"unexpected semicolon or newline before %<{%>");
else
{
this->gogo_->start_function(name, fntype, true, location);
- source_location end_loc = this->block();
+ Location end_loc = this->block();
this->gogo_->finish_function(end_loc);
}
}
std::string name;
const Token* token = this->advance_token();
- source_location location = token->location();
+ Location location = token->location();
if (!token->is_op(OPERATOR_MULT))
{
if (!token->is_identifier())
{
case Token::TOKEN_IDENTIFIER:
{
- source_location location = token->location();
+ Location location = token->location();
std::string id = token->identifier();
bool is_exported = token->is_identifier_exported();
std::string packed = this->gogo_->pack_hidden_name(id, is_exported);
case KEYWORD_MAP:
case KEYWORD_STRUCT:
{
- source_location location = token->location();
+ Location location = token->location();
return Expression::make_type(this->type(), location);
}
default:
{
// Here we call array_type directly, as this is the only
// case where an ellipsis is permitted for an array type.
- source_location location = token->location();
+ Location location = token->location();
return Expression::make_type(this->array_type(true), location);
}
break;
Expression*
Parse::enclosing_var_reference(Named_object* in_function, Named_object* var,
- source_location location)
+ Location location)
{
go_assert(var->is_variable() || var->is_result_variable());
// 1. In [][][]int{{{1}}} it will be 2.
Expression*
-Parse::composite_lit(Type* type, int depth, source_location location)
+Parse::composite_lit(Type* type, int depth, Location location)
{
go_assert(this->peek_token()->is_op(OPERATOR_LCURLY));
this->advance_token();
{
std::string identifier = token->identifier();
bool is_exported = token->is_identifier_exported();
- source_location location = token->location();
+ Location location = token->location();
if (this->advance_token()->is_op(OPERATOR_COLON))
{
Expression*
Parse::function_lit()
{
- source_location location = this->location();
+ Location location = this->location();
go_assert(this->peek_token()->is_keyword(KEYWORD_FUNC));
this->advance_token();
Named_object* no = this->gogo_->start_function("", type, true, location);
- source_location end_loc = this->block();
+ Location end_loc = this->block();
this->gogo_->finish_function(end_loc);
Expression*
Parse::create_closure(Named_object* function, Enclosing_vars* enclosing_vars,
- source_location location)
+ Location location)
{
if (enclosing_vars->empty())
return NULL;
Parse::primary_expr(bool may_be_sink, bool may_be_composite_lit,
bool* is_type_switch)
{
- source_location start_loc = this->location();
+ Location start_loc = this->location();
bool is_parenthesized = this->peek_token()->is_op(OPERATOR_LPAREN);
Expression* ret = this->operand(may_be_sink);
}
else if (this->peek_token()->is_op(OPERATOR_LPAREN))
{
- source_location loc = this->location();
+ Location loc = this->location();
this->advance_token();
Expression* expr = this->expression(PRECEDENCE_NORMAL, false, true,
NULL);
Parse::selector(Expression* left, bool* is_type_switch)
{
go_assert(this->peek_token()->is_op(OPERATOR_DOT));
- source_location location = this->location();
+ Location location = this->location();
const Token* token = this->advance_token();
if (token->is_identifier())
Expression*
Parse::index(Expression* expr)
{
- source_location location = this->location();
+ Location location = this->location();
go_assert(this->peek_token()->is_op(OPERATOR_LSQUARE));
this->advance_token();
// Return an expression for a single unqualified identifier.
Expression*
-Parse::id_to_expression(const std::string& name, source_location location)
+Parse::id_to_expression(const std::string& name, Location location)
{
Named_object* in_function;
Named_object* named_object = this->gogo_->lookup(name, &in_function);
}
Operator op = token->op();
- source_location binop_location = token->location();
+ Location binop_location = token->location();
if (precedence >= right_precedence)
{
|| token->is_op(OPERATOR_MULT)
|| token->is_op(OPERATOR_AND))
{
- source_location location = token->location();
+ Location location = token->location();
Operator op = token->op();
this->advance_token();
{
std::string identifier = token->identifier();
bool is_exported = token->is_identifier_exported();
- source_location location = token->location();
+ Location location = token->location();
if (this->advance_token()->is_op(OPERATOR_COLON))
{
this->advance_token();
case Token::TOKEN_OPERATOR:
if (token->is_op(OPERATOR_LCURLY))
{
- source_location location = token->location();
+ Location location = token->location();
this->gogo_->start_block(location);
- source_location end_loc = this->block();
+ Location end_loc = this->block();
this->gogo_->add_block(this->gogo_->finish_block(end_loc),
location);
}
// Label = identifier .
void
-Parse::labeled_stmt(const std::string& label_name, source_location location)
+Parse::labeled_stmt(const std::string& label_name, Location location)
{
Label* label = this->gogo_->add_label_definition(label_name, location);
{
std::string identifier = token->identifier();
bool is_exported = token->is_identifier_exported();
- source_location location = token->location();
+ Location location = token->location();
token = this->advance_token();
if (token->is_op(OPERATOR_COLONEQ)
Parse::send_stmt(Expression* channel)
{
go_assert(this->peek_token()->is_op(OPERATOR_CHANOP));
- source_location loc = this->location();
+ Location loc = this->location();
this->advance_token();
Expression* val = this->expression(PRECEDENCE_NORMAL, false, true, NULL);
Statement* s = Statement::make_send_statement(channel, val, loc);
return;
}
Operator op = token->op();
- source_location location = token->location();
+ Location location = token->location();
token = this->advance_token();
go_assert(this->peek_token()->is_keyword(KEYWORD_GO)
|| this->peek_token()->is_keyword(KEYWORD_DEFER));
bool is_go = this->peek_token()->is_keyword(KEYWORD_GO);
- source_location stat_location = this->location();
+ Location stat_location = this->location();
this->advance_token();
- source_location expr_location = this->location();
+ Location expr_location = this->location();
Expression* expr = this->expression(PRECEDENCE_NORMAL, false, true, NULL);
Call_expression* call_expr = expr->call_expression();
if (call_expr == NULL)
Parse::return_stat()
{
go_assert(this->peek_token()->is_keyword(KEYWORD_RETURN));
- source_location location = this->location();
+ Location location = this->location();
this->advance_token();
Expression_list* vals = NULL;
if (this->expression_may_start_here())
Parse::if_stat()
{
go_assert(this->peek_token()->is_keyword(KEYWORD_IF));
- source_location location = this->location();
+ Location location = this->location();
this->advance_token();
this->gogo_->start_block(location);
}
this->gogo_->start_block(this->location());
- source_location end_loc = this->block();
+ Location end_loc = this->block();
Block* then_block = this->gogo_->finish_block(end_loc);
// Check for the easy error of a newline before "else".
if (this->peek_token()->is_op(OPERATOR_SEMICOLON))
{
- source_location semi_loc = this->location();
+ Location semi_loc = this->location();
if (this->advance_token()->is_keyword(KEYWORD_ELSE))
error_at(this->location(),
"unexpected semicolon or newline before %<else%>");
Parse::switch_stat(Label* label)
{
go_assert(this->peek_token()->is_keyword(KEYWORD_SWITCH));
- source_location location = this->location();
+ Location location = this->location();
this->advance_token();
this->gogo_->start_block(location);
const Token* token = this->peek_token();
std::string identifier = token->identifier();
bool is_exported = token->is_identifier_exported();
- source_location id_loc = token->location();
+ Location id_loc = token->location();
token = this->advance_token();
bool is_coloneq = token->is_op(OPERATOR_COLONEQ);
if (!this->peek_token()->is_op(OPERATOR_LCURLY))
{
- source_location token_loc = this->location();
+ Location token_loc = this->location();
if (this->peek_token()->is_op(OPERATOR_SEMICOLON)
&& this->advance_token()->is_op(OPERATOR_LCURLY))
error_at(token_loc, "unexpected semicolon or newline before %<{%>");
Statement*
Parse::expr_switch_body(Label* label, Expression* switch_val,
- source_location location)
+ Location location)
{
Switch_statement* statement = Statement::make_switch_statement(switch_val,
location);
void
Parse::expr_case_clause(Case_clauses* clauses, bool* saw_default)
{
- source_location location = this->location();
+ Location location = this->location();
bool is_default = false;
Expression_list* vals = this->expr_switch_case(&is_default);
Statement*
Parse::type_switch_body(Label* label, const Type_switch& type_switch,
- source_location location)
+ Location location)
{
Named_object* switch_no = NULL;
if (!type_switch.name.empty())
Parse::type_case_clause(Named_object* switch_no, Type_case_clauses* clauses,
bool* saw_default)
{
- source_location location = this->location();
+ Location location = this->location();
std::vector<Type*> types;
bool is_default = false;
Parse::select_stat(Label* label)
{
go_assert(this->peek_token()->is_keyword(KEYWORD_SELECT));
- source_location location = this->location();
+ Location location = this->location();
const Token* token = this->advance_token();
if (!token->is_op(OPERATOR_LCURLY))
{
- source_location token_loc = token->location();
+ Location token_loc = token->location();
if (token->is_op(OPERATOR_SEMICOLON)
&& this->advance_token()->is_op(OPERATOR_LCURLY))
error_at(token_loc, "unexpected semicolon or newline before %<{%>");
void
Parse::comm_clause(Select_clauses* clauses, bool* saw_default)
{
- source_location location = this->location();
+ Location location = this->location();
bool is_send = false;
Expression* channel = NULL;
Expression* val = NULL;
Gogo* gogo = this->gogo_;
std::string recv_var = token->identifier();
bool is_rv_exported = token->is_identifier_exported();
- source_location recv_var_loc = token->location();
+ Location recv_var_loc = token->location();
token = this->advance_token();
if (token->is_op(OPERATOR_COLONEQ))
{
{
std::string recv_closed = token->identifier();
bool is_rc_exported = token->is_identifier_exported();
- source_location recv_closed_loc = token->location();
+ Location recv_closed_loc = token->location();
closed_is_id = true;
token = this->advance_token();
Parse::for_stat(Label* label)
{
go_assert(this->peek_token()->is_keyword(KEYWORD_FOR));
- source_location location = this->location();
+ Location location = this->location();
const Token* token = this->advance_token();
// Open a block to hold any variables defined in the init statement
// For_statement.
this->gogo_->start_block(this->location());
- source_location end_loc = this->block();
+ Location end_loc = this->block();
Block* statements = this->gogo_->finish_block(end_loc);
if (sfor != NULL)
Range_clause* p_range_clause)
{
go_assert(this->peek_token()->is_keyword(KEYWORD_RANGE));
- source_location location = this->location();
+ Location location = this->location();
p_range_clause->found = true;
Parse::break_stat()
{
go_assert(this->peek_token()->is_keyword(KEYWORD_BREAK));
- source_location location = this->location();
+ Location location = this->location();
const Token* token = this->advance_token();
Statement* enclosing;
{
// If there is a label with this name, mark it as used to
// avoid a useless error about an unused label.
- this->gogo_->add_label_reference(token->identifier(), 0, false);
+ this->gogo_->add_label_reference(token->identifier(),
+ Linemap::unknown_location(), false);
error_at(token->location(), "invalid break label %qs",
Gogo::message_name(token->identifier()).c_str());
Parse::continue_stat()
{
go_assert(this->peek_token()->is_keyword(KEYWORD_CONTINUE));
- source_location location = this->location();
+ Location location = this->location();
const Token* token = this->advance_token();
Statement* enclosing;
{
// If there is a label with this name, mark it as used to
// avoid a useless error about an unused label.
- this->gogo_->add_label_reference(token->identifier(), 0, false);
+ this->gogo_->add_label_reference(token->identifier(),
+ Linemap::unknown_location(), false);
error_at(token->location(), "invalid continue label %qs",
Gogo::message_name(token->identifier()).c_str());
Parse::goto_stat()
{
go_assert(this->peek_token()->is_keyword(KEYWORD_GOTO));
- source_location location = this->location();
+ Location location = this->location();
const Token* token = this->advance_token();
if (!token->is_identifier())
error_at(this->location(), "expected label for goto");