]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
compiler: Error for qualified ID as field name in struct literal.
authorIan Lance Taylor <ian@gcc.gnu.org>
Tue, 8 Oct 2013 23:54:15 +0000 (23:54 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Tue, 8 Oct 2013 23:54:15 +0000 (23:54 +0000)
From-SVN: r203292

gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/expressions.h
gcc/go/gofrontend/parse.cc

index 13d4c1c789a6fac44813c595f5a01b3629c196e2..d5e3a67625a78b0d1f1024b539e50d5a6def6a91 100644 (file)
@@ -11293,7 +11293,7 @@ Field_reference_expression::do_lower(Gogo* gogo, Named_object* function,
     }
 
   Expression* e = Expression::make_composite_literal(array_type, 0, false,
-                                                    bytes, loc);
+                                                    bytes, false, loc);
 
   Variable* var = new Variable(array_type, e, true, false, false, loc);
 
@@ -13236,9 +13236,11 @@ class Composite_literal_expression : public Parser_expression
 {
  public:
   Composite_literal_expression(Type* type, int depth, bool has_keys,
-                              Expression_list* vals, Location location)
+                              Expression_list* vals, bool all_are_names,
+                              Location location)
     : Parser_expression(EXPRESSION_COMPOSITE_LITERAL, location),
-      type_(type), depth_(depth), vals_(vals), has_keys_(has_keys)
+      type_(type), depth_(depth), vals_(vals), has_keys_(has_keys),
+      all_are_names_(all_are_names)
   { }
 
  protected:
@@ -13256,6 +13258,7 @@ class Composite_literal_expression : public Parser_expression
                                            (this->vals_ == NULL
                                             ? NULL
                                             : this->vals_->copy()),
+                                           this->all_are_names_,
                                            this->location());
   }
 
@@ -13285,6 +13288,9 @@ class Composite_literal_expression : public Parser_expression
   // If this is true, then VALS_ is a list of pairs: a key and a
   // value.  In an array initializer, a missing key will be NULL.
   bool has_keys_;
+  // If this is true, then HAS_KEYS_ is true, and every key is a
+  // simple identifier.
+  bool all_are_names_;
 };
 
 // Traversal.
@@ -13387,6 +13393,8 @@ Composite_literal_expression::lower_struct(Gogo* gogo, Type* type)
   std::vector<Expression*> vals(field_count);
   std::vector<int>* traverse_order = new(std::vector<int>);
   Expression_list::const_iterator p = this->vals_->begin();
+  Expression* external_expr = NULL;
+  const Named_object* external_no = NULL;
   while (p != this->vals_->end())
     {
       Expression* name_expr = *p;
@@ -13492,6 +13500,12 @@ Composite_literal_expression::lower_struct(Gogo* gogo, Type* type)
 
       if (no != NULL)
        {
+         if (no->package() != NULL && external_expr == NULL)
+           {
+             external_expr = name_expr;
+             external_no = no;
+           }
+
          name = no->name();
 
          // A predefined name won't be packed.  If it starts with a
@@ -13541,6 +13555,23 @@ Composite_literal_expression::lower_struct(Gogo* gogo, Type* type)
       traverse_order->push_back(index);
     }
 
+  if (!this->all_are_names_)
+    {
+      // This is a weird case like bug462 in the testsuite.
+      if (external_expr == NULL)
+       error_at(this->location(), "unknown field in %qs literal",
+                (type->named_type() != NULL
+                 ? type->named_type()->message_name().c_str()
+                 : "unnamed struct"));
+      else
+       error_at(external_expr->location(), "unknown field %qs in %qs",
+                external_no->message_name().c_str(),
+                (type->named_type() != NULL
+                 ? type->named_type()->message_name().c_str()
+                 : "unnamed struct"));
+      return Expression::make_error(location);
+    }
+
   Expression_list* list = new Expression_list;
   list->reserve(field_count);
   for (size_t i = 0; i < field_count; ++i)
@@ -13830,11 +13861,11 @@ Composite_literal_expression::do_dump_expression(
 
 Expression*
 Expression::make_composite_literal(Type* type, int depth, bool has_keys,
-                                  Expression_list* vals,
+                                  Expression_list* vals, bool all_are_names,
                                   Location location)
 {
   return new Composite_literal_expression(type, depth, has_keys, vals,
-                                         location);
+                                         all_are_names, location);
 }
 
 // Return whether this expression is a composite literal.
index b4cca5453b08dae173980900eed44c24cc37e634..bc7a25f766a7bd1d015b6e2f06e8199d952d011b 100644 (file)
@@ -291,10 +291,13 @@ class Expression
   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.
+  // are in a list of composite literals with omitted types.  HAS_KEYS
+  // is true if the expression list has keys alternating with values.
+  // ALL_ARE_NAMES is true if all the keys could be struct field
+  // names.
   static Expression*
   make_composite_literal(Type*, int depth, bool has_keys, Expression_list*,
-                        Location);
+                        bool all_are_names, Location);
 
   // Make a struct composite literal.
   static Expression*
index e68f1753f8784e8775d6fe0aff04df23d7329914..498125bb2410272bd056a62bb1df51a7a1b949fb 100644 (file)
@@ -2690,15 +2690,17 @@ Parse::composite_lit(Type* type, int depth, Location location)
     {
       this->advance_token();
       return Expression::make_composite_literal(type, depth, false, NULL,
-                                               location);
+                                               false, location);
     }
 
   bool has_keys = false;
+  bool all_are_names = true;
   Expression_list* vals = new Expression_list;
   while (true)
     {
       Expression* val;
       bool is_type_omitted = false;
+      bool is_name = false;
 
       const Token* token = this->peek_token();
 
@@ -2719,6 +2721,7 @@ Parse::composite_lit(Type* type, int depth, Location location)
              val = this->id_to_expression(gogo->pack_hidden_name(identifier,
                                                                  is_exported),
                                           location);
+             is_name = true;
            }
          else
            {
@@ -2744,6 +2747,7 @@ Parse::composite_lit(Type* type, int depth, Location location)
        {
          if (has_keys)
            vals->push_back(NULL);
+         is_name = false;
        }
       else
        {
@@ -2790,6 +2794,9 @@ Parse::composite_lit(Type* type, int depth, Location location)
 
       vals->push_back(val);
 
+      if (!is_name)
+       all_are_names = false;
+
       if (token->is_op(OPERATOR_COMMA))
        {
          if (this->advance_token()->is_op(OPERATOR_RCURLY))
@@ -2830,7 +2837,7 @@ Parse::composite_lit(Type* type, int depth, Location location)
     }
 
   return Expression::make_composite_literal(type, depth, has_keys, vals,
-                                           location);
+                                           all_are_names, location);
 }
 
 // FunctionLit = "func" Signature Block .