re PR c++/18001 (Badly formatted error message (quotation problem))
authorMark Mitchell <mark@codesourcery.com>
Thu, 25 Nov 2004 17:11:37 +0000 (17:11 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Thu, 25 Nov 2004 17:11:37 +0000 (17:11 +0000)
PR c++/18001
* c-common.h (lvalue_use): Move here from c-ctypeck.c.
(lvalue_or_else): Declare.
* c-common.c (lvalue_or_else): Move here from c-typeck.c.
* c-typeck.c (lvalue_use): Remove.
(lvalue_or_else): Remove.

PR c++/18556
* toplev.c (check_global_declarations): Set DECL_IGNORED_P on
unemitted variables with static storage duration.

PR c++/18445
* class.c (instantiate_type): Treat NON_DEPENDENT_EXPRs with
unknown_type as non matching.  Tidy up.
* pt.c (build_non_dependent_expr): Do not build a
NON_DEPENDENT_EXPR for a VAR_DECL.

PR c++/18001
* cp-tree.h (lvalue_or_else): Remove declaration.
* tree.c (lvalue_or_else): Remove.
* typeck.c (build_unary_op): Adjust call to lvalue_or_else.
(build_modify_expr): Likewise.

PR c++/18625
* decl.c (duplicate_decls): Return error_mark_node on error, as
specified.

PR c++/18466
* decl.c (grokvardecl): Keep track of whether or not a there was
explicit qualification.
* name-lookup.c (set_decl_namespace): Complain about explicit
qualification of a name within its own namespace.

PR c++/18545
* typeck.c (check_return_expr): Robustify.

PR c++/18445
* g++.dg/template/crash28.C: Likewise.

PR c++/18001
* g++.dg/expr/unary2.C: Adjust lvalue messages.
* g++.dg/ext/lvaddr.C: Likewise.
* g++.dg/opt/pr7503-3.C: Likewise.

PR c++/18466
* g++.dg/parse/qualified3.C: New test.
* g++.old-deja/g++.other/friend7.C: Remove bogus qualification.

PR c++/18545
* g++.dg/expr/return1.C: New test.

From-SVN: r91301

21 files changed:
gcc/ChangeLog
gcc/c-common.c
gcc/c-common.h
gcc/c-typeck.c
gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/name-lookup.c
gcc/cp/pt.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/expr/return1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/expr/unary2.C
gcc/testsuite/g++.dg/ext/lvaddr.C
gcc/testsuite/g++.dg/opt/pr7503-3.C
gcc/testsuite/g++.dg/parse/qualified3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/crash28.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.other/friend7.C
gcc/toplev.c

index a8cdba270b9c87255694dfe7f73a2a404bf75898..0f8ebea5cc52785050bef055bb249c3c08594892 100644 (file)
@@ -1,3 +1,16 @@
+2004-11-25  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/18001
+       * c-common.h (lvalue_use): Move here from c-ctypeck.c.
+       (lvalue_or_else): Declare.
+       * c-common.c (lvalue_or_else): Move here from c-typeck.c.
+       * c-typeck.c (lvalue_use): Remove.
+       (lvalue_or_else): Remove.
+
+       PR c++/18556
+       * toplev.c (check_global_declarations): Set DECL_IGNORED_P on
+       unemitted variables with static storage duration.
+
 2004-11-25  Gerald Pfeifer  <gerald@pfeifer.com>
 
        * tree-cfg.c (tree_verify_flow_info): Do not terminate error()
index 81bdbbf625436e192b6df4e6ac9ac5c149a35f8f..bfefeb231dcb24fd6f7df9122d4e6ef27d81fd25 100644 (file)
@@ -5617,4 +5617,40 @@ fold_offsetof (tree expr)
   return convert (size_type_node, fold_offsetof_1 (expr));
 }
 
+/* Return nonzero if REF is an lvalue valid for this language;
+   otherwise, print an error message and return zero.  USE says
+   how the lvalue is being used and so selects the error message.  */
+
+int
+lvalue_or_else (tree ref, enum lvalue_use use)
+{
+  int win = lvalue_p (ref);
+
+  if (!win)
+    {
+      switch (use)
+       {
+       case lv_assign:
+         error ("invalid lvalue in assignment");
+         break;
+       case lv_increment:
+         error ("invalid lvalue in increment");
+         break;
+       case lv_decrement:
+         error ("invalid lvalue in decrement");
+         break;
+       case lv_addressof:
+         error ("invalid lvalue in unary %<&%>");
+         break;
+       case lv_asm:
+         error ("invalid lvalue in asm statement");
+         break;
+       default:
+         gcc_unreachable ();
+       }
+    }
+
+  return win;
+}
+
 #include "gt-c-common.h"
index 63c095c07811bda465942f06a8253b0ae7efafd6..d0fbaa837dfdedbb2d3c3ee73a6772e4877eb4a9 100644 (file)
@@ -873,6 +873,19 @@ extern void verify_sequence_points (tree);
 
 extern tree fold_offsetof (tree);
 
+/* Places where an lvalue, or modifiable lvalue, may be required.
+   Used to select diagnostic messages in lvalue_or_else and
+   readonly_error.  */
+enum lvalue_use {
+  lv_assign,
+  lv_increment,
+  lv_decrement,
+  lv_addressof,
+  lv_asm
+};
+
+extern int lvalue_or_else (tree, enum lvalue_use);
+
 /* In c-gimplify.c  */
 extern void c_genericize (tree);
 extern int c_gimplify_expr (tree *, tree *, tree *);
index c5401042b66b61bf983bb3e2dc4ed2bcf50d0b7e..23ff80e10de279baee352c428be0d3e9301c7a31 100644 (file)
@@ -44,17 +44,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "tree-iterator.h"
 #include "tree-gimple.h"
 
-/* Places where an lvalue, or modifiable lvalue, may be required.
-   Used to select diagnostic messages in lvalue_or_else and
-   readonly_error.  */
-enum lvalue_use {
-  lv_assign,
-  lv_increment,
-  lv_decrement,
-  lv_addressof,
-  lv_asm
-};
-
 /* Possible cases of implicit bad conversions.  Used to select
    diagnostic messages in convert_for_assignment.  */
 enum impl_conv {
@@ -109,7 +98,6 @@ static void add_pending_init (tree, tree);
 static void set_nonincremental_init (void);
 static void set_nonincremental_init_from_string (tree);
 static tree find_init_member (tree);
-static int lvalue_or_else (tree, enum lvalue_use);
 static void readonly_error (tree, enum lvalue_use);
 static void record_maybe_used_decl (tree);
 \f
@@ -2714,43 +2702,6 @@ lvalue_p (tree ref)
       return 0;
     }
 }
-
-/* Return nonzero if REF is an lvalue valid for this language;
-   otherwise, print an error message and return zero.  USE says
-   how the lvalue is being used and so selects the error message.  */
-
-static int
-lvalue_or_else (tree ref, enum lvalue_use use)
-{
-  int win = lvalue_p (ref);
-
-  if (!win)
-    {
-      switch (use)
-       {
-       case lv_assign:
-         error ("invalid lvalue in assignment");
-         break;
-       case lv_increment:
-         error ("invalid lvalue in increment");
-         break;
-       case lv_decrement:
-         error ("invalid lvalue in decrement");
-         break;
-       case lv_addressof:
-         error ("invalid lvalue in unary %<&%>");
-         break;
-       case lv_asm:
-         error ("invalid lvalue in asm statement");
-         break;
-       default:
-         gcc_unreachable ();
-       }
-    }
-
-  return win;
-}
-
 \f
 /* Give an error for storing in something that is 'const'.  */
 
index e79b20e559267c2586c6ac700d5c18cf41bce0e2..6a8aea8e4e184cb190bd57cc13818b4b6bb000b6 100644 (file)
@@ -1,3 +1,30 @@
+2004-11-25  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/18445
+       * class.c (instantiate_type): Treat NON_DEPENDENT_EXPRs with
+       unknown_type as non matching.  Tidy up.
+       * pt.c (build_non_dependent_expr): Do not build a
+       NON_DEPENDENT_EXPR for a VAR_DECL.
+
+       PR c++/18001
+       * cp-tree.h (lvalue_or_else): Remove declaration.
+       * tree.c (lvalue_or_else): Remove.
+       * typeck.c (build_unary_op): Adjust call to lvalue_or_else.
+       (build_modify_expr): Likewise.
+
+       PR c++/18625
+       * decl.c (duplicate_decls): Return error_mark_node on error, as
+       specified.
+
+       PR c++/18466
+       * decl.c (grokvardecl): Keep track of whether or not a there was
+       explicit qualification.
+       * name-lookup.c (set_decl_namespace): Complain about explicit
+       qualification of a name within its own namespace.
+
+       PR c++/18545
+       * typeck.c (check_return_expr): Robustify.
+
 2004-11-25  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>
 
        Friend class name lookup 3/n, PR c++/3332
index e146abc0223ed7042854ffe006e347a8625cb14a..3db223a8717cb533c03fcf0741e1caa291798ae2 100644 (file)
@@ -5864,6 +5864,15 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags)
   if (TREE_CODE (rhs) == BASELINK)
     rhs = BASELINK_FUNCTIONS (rhs);
 
+  /* If we are in a template, and have a NON_DEPENDENT_EXPR, we cannot
+     deduce any type information.  */
+  if (TREE_CODE (rhs) == NON_DEPENDENT_EXPR)
+    {
+      if (flags & tf_error)
+       error ("not enough type information");
+      return error_mark_node;
+    }
+
   /* We don't overwrite rhs if it is an overloaded function.
      Copying it would destroy the tree link.  */
   if (TREE_CODE (rhs) != OVERLOAD)
@@ -5904,14 +5913,15 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags)
 
     case COMPONENT_REF:
       {
-       tree addr = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags);
+       tree member = TREE_OPERAND (rhs, 1);
 
-       if (addr != error_mark_node
+       member = instantiate_type (lhstype, member, flags);
+       if (member != error_mark_node
            && TREE_SIDE_EFFECTS (TREE_OPERAND (rhs, 0)))
          /* Do not lose object's side effects.  */
-         addr = build2 (COMPOUND_EXPR, TREE_TYPE (addr),
-                        TREE_OPERAND (rhs, 0), addr);
-       return addr;
+         return build2 (COMPOUND_EXPR, TREE_TYPE (member),
+                        TREE_OPERAND (rhs, 0), member);
+       return member;
       }
 
     case OFFSET_REF:
@@ -5943,12 +5953,6 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags)
                                                /*template_only=*/false,
                                                /*explicit_targs=*/NULL_TREE);
 
-    case TREE_LIST:
-      /* Now we should have a baselink.  */
-      gcc_assert (BASELINK_P (rhs));
-
-      return instantiate_type (lhstype, BASELINK_FUNCTIONS (rhs), flags);
-
     case CALL_EXPR:
       /* This is too hard for now.  */
       gcc_unreachable ();
index 0f0bfb290679c55a80eb47421629c3202a91123f..f6da43c82870915374ce104454ab9721c2daba3c 100644 (file)
@@ -4186,7 +4186,6 @@ extern tree copy_binfo                            (tree, tree, tree,
                                                 tree *, int);
 extern int member_p                            (tree);
 extern cp_lvalue_kind real_lvalue_p             (tree);
-extern int lvalue_or_else                      (tree, const char *);
 extern tree build_min                          (enum tree_code, tree, ...);
 extern tree build_min_nt                       (enum tree_code, ...);
 extern tree build_min_non_dep                  (enum tree_code, tree, ...);
index 98ca4f944ad870d56e0268ccbcd3a90adb066a7e..2085a57fff29308ec93e14dc7eddab548f24fcd4 100644 (file)
@@ -1417,7 +1417,7 @@ duplicate_decls (tree newdecl, tree olddecl)
          error ("conflicting declaration %q#D", newdecl);
          cp_error_at ("%qD has a previous declaration as %q#D",
                        olddecl, olddecl);
-          return NULL_TREE;
+          return error_mark_node;
        }
     }
   else if (TREE_CODE (newdecl) == FUNCTION_DECL
@@ -5921,10 +5921,13 @@ grokvardecl (tree type,
              tree scope)
 {
   tree decl;
+  tree explicit_scope;
 
   gcc_assert (!name || TREE_CODE (name) == IDENTIFIER_NODE);
 
-  /* Compute the scope in which to place the variable.  */
+  /* Compute the scope in which to place the variable, but remember
+     whether or not that scope was explicitly specified by the user.   */
+  explicit_scope = scope;
   if (!scope)
     {
       /* An explicit "extern" specifier indicates a namespace-scope
@@ -5949,8 +5952,8 @@ grokvardecl (tree type,
   else
     decl = build_decl (VAR_DECL, name, type);
 
-  if (scope && TREE_CODE (scope) == NAMESPACE_DECL)
-    set_decl_namespace (decl, scope, 0);
+  if (explicit_scope && TREE_CODE (explicit_scope) == NAMESPACE_DECL)
+    set_decl_namespace (decl, explicit_scope, 0);
   else
     DECL_CONTEXT (decl) = scope;
 
index aa5e5d24454ac57718b876225eb96c8d736ab718..14c94a890449e5f3d115f3d42b15d1ec3785c538 100644 (file)
@@ -3114,42 +3114,46 @@ set_decl_namespace (tree decl, tree scope, bool friendp)
     error ("declaration of %qD not in a namespace surrounding %qD",
            decl, scope);
   DECL_CONTEXT (decl) = FROB_CONTEXT (scope);
-  if (scope != current_namespace)
-    {
-      /* See whether this has been declared in the namespace.  */
-      old = namespace_binding (DECL_NAME (decl), scope);
-      if (!old)
-       /* No old declaration at all.  */
-       goto complain;
-      /* A template can be explicitly specialized in any namespace.  */
-      if (processing_explicit_instantiation)
-       return;
-      if (!is_overloaded_fn (decl))
-       /* Don't compare non-function decls with decls_match here,
-          since it can't check for the correct constness at this
-          point. pushdecl will find those errors later.  */
-       return;
-      /* Since decl is a function, old should contain a function decl.  */
-      if (!is_overloaded_fn (old))
-       goto complain;
-      if (processing_template_decl || processing_specialization)
-       /* We have not yet called push_template_decl to turn a
-          FUNCTION_DECL into a TEMPLATE_DECL, so the declarations
-          won't match.  But, we'll check later, when we construct the
-          template.  */
-       return;
-      if (is_overloaded_fn (old))
-       {
-         for (; old; old = OVL_NEXT (old))
-           if (decls_match (decl, OVL_CURRENT (old)))
-             return;
-       }
-      else
-       if (decls_match (decl, old))
-         return;
+
+  /* Writing "int N::i" to declare a variable within "N" is invalid.  */ 
+  if (scope == current_namespace) 
+    {
+      if (at_namespace_scope_p ())
+       error ("explicit qualification in declaration of `%D'",
+              decl);
+      return;
     }
-  else
+
+  /* See whether this has been declared in the namespace.  */
+  old = namespace_binding (DECL_NAME (decl), scope);
+  if (!old)
+    /* No old declaration at all.  */
+    goto complain;
+  /* A template can be explicitly specialized in any namespace.  */
+  if (processing_explicit_instantiation)
+    return;
+  if (!is_overloaded_fn (decl))
+    /* Don't compare non-function decls with decls_match here, since
+       it can't check for the correct constness at this
+       point. pushdecl will find those errors later.  */
+    return;
+  /* Since decl is a function, old should contain a function decl.  */
+  if (!is_overloaded_fn (old))
+    goto complain;
+  if (processing_template_decl || processing_specialization)
+    /* We have not yet called push_template_decl to turn a
+       FUNCTION_DECL into a TEMPLATE_DECL, so the declarations won't
+       match.  But, we'll check later, when we construct the
+       template.  */
     return;
+  if (is_overloaded_fn (old))
+    {
+      for (; old; old = OVL_NEXT (old))
+       if (decls_match (decl, OVL_CURRENT (old)))
+         return;
+    }
+  else if (decls_match (decl, old))
+      return;
  complain:
   error ("%qD should have been declared inside %qD", decl, scope);
 } 
index b514cc1430137d0cf36a542a5a382d1f2bcde727..cc11f364d306766bb7744be8c1f0d1442b9ddf7a 100644 (file)
@@ -12296,6 +12296,9 @@ build_non_dependent_expr (tree expr)
       || TREE_CODE (inner_expr) == TEMPLATE_DECL
       || TREE_CODE (inner_expr) == TEMPLATE_ID_EXPR)
     return expr;
+  /* There is no need to return a proxy for a variable.  */
+  if (TREE_CODE (expr) == VAR_DECL)
+    return expr;
   /* Preserve string constants; conversions from string constants to
      "char *" are allowed, even though normally a "const char *"
      cannot be used to initialize a "char *".  */
index 82aebe49550e887004b66b5e081e45da9da55848..a4b470ecda249eea74315c21a0f757adcaa49ff2 100644 (file)
@@ -215,20 +215,6 @@ lvalue_p (tree ref)
     (lvalue_p_1 (ref, /*class rvalue ok*/ 1) != clk_none);
 }
 
-/* Return nonzero if REF is an lvalue valid for this language;
-   otherwise, print an error message and return zero.  */
-
-int
-lvalue_or_else (tree ref, const char* string)
-{
-  if (!lvalue_p (ref))
-    {
-      error ("non-lvalue in %s", string);
-      return 0;
-    }
-  return 1;
-}
-
 /* Build a TARGET_EXPR, initializing the DECL with the VALUE.  */
 
 static tree
index 60f03c97387f047a25c14e1307a9798421fe5f66..149a38896c7258c2225e20da8d422df5209d795f 100644 (file)
@@ -3956,7 +3956,7 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
        /* Complain about anything else that is not a true lvalue.  */
        if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
                                    || code == POSTINCREMENT_EXPR)
-                                  ? "increment" : "decrement")))
+                                  ? lv_increment : lv_decrement)))
          return error_mark_node;
 
        /* Forbid using -- on `bool'.  */
@@ -4100,7 +4100,7 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
         is an error.  */
       else if (TREE_CODE (argtype) != FUNCTION_TYPE
               && TREE_CODE (argtype) != METHOD_TYPE
-              && !lvalue_or_else (arg, "unary %<&$>"))
+              && !lvalue_or_else (arg, lv_addressof))
        return error_mark_node;
 
       if (argtype != error_mark_node)
@@ -5294,7 +5294,7 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
     case MAX_EXPR:
       /* MIN_EXPR and MAX_EXPR are currently only permitted as lvalues,
         when neither operand has side-effects.  */
-      if (!lvalue_or_else (lhs, "assignment"))
+      if (!lvalue_or_else (lhs, lv_assign))
        return error_mark_node;
 
       gcc_assert (!TREE_SIDE_EFFECTS (TREE_OPERAND (lhs, 0))
@@ -5322,7 +5322,7 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
        
        /* Check this here to avoid odd errors when trying to convert
           a throw to the type of the COND_EXPR.  */
-       if (!lvalue_or_else (lhs, "assignment"))
+       if (!lvalue_or_else (lhs, lv_assign))
          return error_mark_node;
 
        cond = build_conditional_expr
@@ -5421,7 +5421,7 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
     }
 
   /* The left-hand side must be an lvalue.  */
-  if (!lvalue_or_else (lhs, "assignment"))
+  if (!lvalue_or_else (lhs, lv_assign))
     return error_mark_node;
 
   /* Warn about modifying something that is `const'.  Don't warn if
@@ -6230,6 +6230,15 @@ check_return_expr (tree retval)
     /* Remember that this function did return a value.  */
     current_function_returns_value = 1;
 
+  /* Check for errnoneous operands -- but after giving ourselves a
+     chance to provide an error about returning a value from a void
+     function.  */
+  if (error_operand_p (retval))
+    {
+      current_function_return_value = error_mark_node;
+      return error_mark_node;
+    }
+
   /* Only operator new(...) throw(), can return NULL [expr.new/13].  */
   if ((DECL_OVERLOADED_OPERATOR_P (current_function_decl) == NEW_EXPR
        || DECL_OVERLOADED_OPERATOR_P (current_function_decl) == VEC_NEW_EXPR)
@@ -6305,8 +6314,8 @@ check_return_expr (tree retval)
 
   /* We don't need to do any conversions when there's nothing being
      returned.  */
-  if (!retval || retval == error_mark_node)
-    return retval;
+  if (!retval)
+    return NULL_TREE;
 
   /* Do any required conversions.  */
   if (retval == result || DECL_CONSTRUCTOR_P (current_function_decl))
index 934cb9aa81e8579b0952df6ca6f9526943ea3d72..dc9628f6d61268cfc46a29c0eb5563e3b502f30a 100644 (file)
@@ -1,3 +1,20 @@
+2004-11-25  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/18445
+       * g++.dg/template/crash28.C: Likewise.
+
+       PR c++/18001
+       * g++.dg/expr/unary2.C: Adjust lvalue messages.
+       * g++.dg/ext/lvaddr.C: Likewise.
+       * g++.dg/opt/pr7503-3.C: Likewise.
+
+       PR c++/18466
+       * g++.dg/parse/qualified3.C: New test.
+       * g++.old-deja/g++.other/friend7.C: Remove bogus qualification.
+       
+       PR c++/18545
+       * g++.dg/expr/return1.C: New test. 
+
 2004-11-25  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>
 
        Friend class name lookup 3/n, PR c++/3332
diff --git a/gcc/testsuite/g++.dg/expr/return1.C b/gcc/testsuite/g++.dg/expr/return1.C
new file mode 100644 (file)
index 0000000..7a64988
--- /dev/null
@@ -0,0 +1,9 @@
+// PR c++/18545
+
+struct A;
+
+A foo()  // { dg-error "" }
+{
+  A a; // { dg-error "" }
+  return a;
+}
index 9d6acc844883f6a8dfe43c16bdc16198a56c655d..8418815918fb71cf09584f3c9a7a5e48a6bc5e2f 100644 (file)
@@ -8,13 +8,13 @@ int n;
 
 void f(void)
 {
-  -n = 0;        // { dg-error "non-lvalue" }
-  +n = 0;        // { dg-error "non-lvalue" }
+  -n = 0;        // { dg-error "lvalue" }
+  +n = 0;        // { dg-error "lvalue" }
 }
 
 template <int>
 void g(void)
 {
-  -n = 0;        // { dg-error "non-lvalue" "" { xfail *-*-* } }
-  +n = 0;        // { dg-error "non-lvalue" "" { xfail *-*-* } }
+  -n = 0;        // { dg-error "lvalue" "" { xfail *-*-* } }
+  +n = 0;        // { dg-error "lvalue" "" { xfail *-*-* } }
 }
index 184afce900b6bca344c3901041446d73bb53891b..5b217d165949b77f3136652726bcefd57c29b303 100644 (file)
@@ -6,5 +6,5 @@
 void f()
 {
   int n;
-  char* p = &(char) n;         // { dg-error "non-lvalue" }
+  char* p = &(char) n;         // { dg-error "lvalue" }
 }
index ed223f4dc2c468dd112fae5b5d74cdb841100688..34d91ddb6c0d5aba98397185d98011aa7992bbec 100644 (file)
@@ -6,21 +6,21 @@ extern int A, B;
 
 void test1()
 {
-  (A++ <? B) = 0;  // { dg-error "non-lvalue in assignment" }
+  (A++ <? B) = 0;  // { dg-error "lvalue in assignment" }
 }
 
 void test2()
 {
-  (A <? B++) = 0;  // { dg-error "non-lvalue in assignment" }
+  (A <? B++) = 0;  // { dg-error "lvalue in assignment" }
 }
 
 void test3()
 {
-  (A++ >? B) = 0;  // { dg-error "non-lvalue in assignment" }
+  (A++ >? B) = 0;  // { dg-error "lvalue in assignment" }
 }
 
 void test4()
 {
-  (A >? B++) = 0;  // { dg-error "non-lvalue in assignment" }
+  (A >? B++) = 0;  // { dg-error "lvalue in assignment" }
 }
 
diff --git a/gcc/testsuite/g++.dg/parse/qualified3.C b/gcc/testsuite/g++.dg/parse/qualified3.C
new file mode 100644 (file)
index 0000000..ab160ab
--- /dev/null
@@ -0,0 +1,8 @@
+// PR c++/18466
+
+int ::i; // { dg-error "" }
+void ::f(); // { dg-error "" }
+namespace N {
+  int N::j; // { dg-error "" }
+  void N::g(); // { dg-error "" }
+}
diff --git a/gcc/testsuite/g++.dg/template/crash28.C b/gcc/testsuite/g++.dg/template/crash28.C
new file mode 100644 (file)
index 0000000..e8b2bbb
--- /dev/null
@@ -0,0 +1,13 @@
+// PR c++/18445
+
+struct a
+{
+  int what();
+};
+void g(void*);
+template<class T>
+void f()
+{
+  a ex;
+  g(ex.what); // { dg-error "" }
+}
index 1055d99ceae74a49e62471e36879458863261211..aed56a187ddf4b503176573de3efd4830db61a2b 100644 (file)
@@ -15,7 +15,7 @@ class S {
 };
 } 
 
-void (::foo)(M::S *ptr) {
+void (foo)(M::S *ptr) {
   M::S::s.Fn();
   ptr->Fn();
 } 
index 29ae0651426b8a0379023ea790316554c8204856..e2efecd563ca41fcb0c5e726656afc6ca8a3865c 100644 (file)
@@ -819,6 +819,13 @@ check_global_declarations (tree *vec, int len)
     {
       decl = vec[i];
 
+      /* Do not emit debug information about variables that are in
+        static storage, but not defined.  */
+      if (TREE_CODE (decl) == VAR_DECL
+         && TREE_STATIC (decl)
+         && !TREE_ASM_WRITTEN (decl))
+       DECL_IGNORED_P (decl) = 1;
       /* Warn about any function
         declared static but not defined.
         We don't warn about variables,