On Mon, 9 Jan 2017, Marek Polacek wrote:

> On Thu, Jan 05, 2017 at 04:41:28PM +0100, Jakub Jelinek wrote:
> > On Thu, Jan 05, 2017 at 04:39:40PM +0100, Marek Polacek wrote:
> > > Coming back to this...
> > 
> > > > Right, after h0 == h1 is missing && operand_equal_p (thenb, elseb, 0)
> > > > or so (the exact last operand needs to be figured out).
> > > > OEP_ONLY_CONST is certainly wrong, we want the same VAR_DECLs to mean 
> > > > the
> > > > same thing.  0 is a tiny bit better, but still it will give up on e.g. 
> > > > pure
> > > > and other calls.  OEP_PURE_SAME is tiny bit better than that, but still
> > > > calls with the same arguments to the same function will not be 
> > > > considered
> > > > equal, plus likely operand_equal_p doesn't handle STATEMENT_LIST etc.
> > > > So maybe we need another OEP_* mode for this.
> > > 
> > > Yea, if I add "&& operand_equal_p (thenb, elseb, 0)" then this warning 
> > > doesn't
> > > trigger for certain cases, such as MODIFY_EXPR, RETURN_EXPR, probably
> > > STATEMENT_LIST and others.  So I suppose I could introduce a new OEP_ 
> > > mode for
> > > this (names?  OEP_EXTENDED?) and then in operand_equal_p in case 
> > > tcc_expression
> > > do
> > > 
> > >   case MODIFY_EXPR:
> > >     if (flags & OEP_EXTENDED)
> > >       // compare LHS and RHS of both
> > >      
> > > ?
> > 
> > Yeah.  Not sure what is the best name for that.  Maybe Richi has some clever
> > ideas.
> 
> Here it is.  The changes in operand_equal_p should only trigger with the new
> OEP_LEXICOGRAPHIC, and given the macro location issue, the warning isn't yet
> enabled by neither -Wall nor -Wextra, so this all should be safe.
> 
> Bootstrapped/regtested on x86_64-linux, ok for trunk?

@@ -2722,6 +2722,9 @@ combine_comparisons (location_t loc,
    If OEP_ADDRESS_OF is set, we are actually comparing addresses of
objects,
    not values of expressions.
 
+   If OEP_LEXICOGRAPHIC is set, then also handle expressions such as
+   MODIFY_EXPR, RETURN_EXPR, as well as STATEMENT_LISTs.
+

I'd say "also handle expressions with side-effects such as ..."

otherwise the middle-end changes look good to me - I'll defer to
C FE maintainers for the rest.

Thanks,
Richard.

> 2017-01-09  Marek Polacek  <pola...@redhat.com>
> 
>       PR c/64279
>       * c-common.h (do_warn_duplicated_branches_r): Declare.
>       * c-gimplify.c (c_genericize): Walk the function tree calling
>       do_warn_duplicated_branches_r.
>       * c-warn.c (expr_from_macro_expansion_r): New.
>       (do_warn_duplicated_branches): New.
>       (do_warn_duplicated_branches_r): New.
>       * c.opt (Wduplicated-branches): New option.
> 
>       * c-typeck.c (build_conditional_expr): Warn about duplicated branches.
> 
>       * call.c (build_conditional_expr_1): Warn about duplicated branches.
>       * semantics.c (finish_expr_stmt): Build statement using the proper
>       location.
> 
>       * doc/invoke.texi: Document -Wduplicated-branches.
>       * fold-const.c (operand_equal_p): Handle MODIFY_EXPR, INIT_EXPR,
>       COMPOUND_EXPR, PREDECREMENT_EXPR, PREINCREMENT_EXPR,
>       POSTDECREMENT_EXPR, POSTINCREMENT_EXPR, CLEANUP_POINT_EXPR, EXPR_STMT,
>       STATEMENT_LIST, and RETURN_EXPR.  For non-pure non-const functions
>       return 0 only when not OEP_LEXICOGRAPHIC.
>       (fold_build_cleanup_point_expr): Use the expression
>       location when building CLEANUP_POINT_EXPR.
>       * tree-core.h (enum operand_equal_flag): Add OEP_LEXICOGRAPHIC.
>       * tree.c (add_expr): Handle error_mark_node.
> 
>       * c-c++-common/Wduplicated-branches-1.c: New test.
>       * c-c++-common/Wduplicated-branches-10.c: New test.
>       * c-c++-common/Wduplicated-branches-11.c: New test.
>       * c-c++-common/Wduplicated-branches-12.c: New test.
>       * c-c++-common/Wduplicated-branches-2.c: New test.
>       * c-c++-common/Wduplicated-branches-3.c: New test.
>       * c-c++-common/Wduplicated-branches-4.c: New test.
>       * c-c++-common/Wduplicated-branches-5.c: New test.
>       * c-c++-common/Wduplicated-branches-6.c: New test.
>       * c-c++-common/Wduplicated-branches-7.c: New test.
>       * c-c++-common/Wduplicated-branches-8.c: New test.
>       * c-c++-common/Wduplicated-branches-9.c: New test.
>       * c-c++-common/Wimplicit-fallthrough-7.c: Coalesce dg-warning.
>       * g++.dg/cpp0x/lambda/lambda-switch.C: Move dg-warning.
>       * g++.dg/ext/builtin-object-size3.C: Likewise.
>       * g++.dg/gomp/loop-1.C: Likewise.
>       * g++.dg/warn/Wduplicated-branches1.C: New test.
>       * g++.dg/warn/Wduplicated-branches2.C: New test.
> 
> diff --git gcc/c-family/c-common.h gcc/c-family/c-common.h
> index b838869..06918db 100644
> --- gcc/c-family/c-common.h
> +++ gcc/c-family/c-common.h
> @@ -1537,6 +1537,7 @@ extern void maybe_warn_bool_compare (location_t, enum 
> tree_code, tree, tree);
>  extern bool maybe_warn_shift_overflow (location_t, tree, tree);
>  extern void warn_duplicated_cond_add_or_warn (location_t, tree, vec<tree> 
> **);
>  extern bool diagnose_mismatched_attributes (tree, tree);
> +extern tree do_warn_duplicated_branches_r (tree *, int *, void *);
>  
>  /* In c-attribs.c.  */
>  extern bool attribute_takes_identifier_p (const_tree);
> diff --git gcc/c-family/c-gimplify.c gcc/c-family/c-gimplify.c
> index c327ca7..57edb41 100644
> --- gcc/c-family/c-gimplify.c
> +++ gcc/c-family/c-gimplify.c
> @@ -125,6 +125,10 @@ c_genericize (tree fndecl)
>                &pset);
>      }
>  
> +  if (warn_duplicated_branches)
> +    walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
> +                               do_warn_duplicated_branches_r, NULL);
> +
>    /* Dump the C-specific tree IR.  */
>    dump_orig = get_dump_info (TDI_original, &local_dump_flags);
>    if (dump_orig)
> diff --git gcc/c-family/c-warn.c gcc/c-family/c-warn.c
> index 1dbf47e..3c9077c 100644
> --- gcc/c-family/c-warn.c
> +++ gcc/c-family/c-warn.c
> @@ -2217,3 +2217,73 @@ warn_for_restrict (unsigned param_pos, vec<tree, 
> va_gc> *args)
>  
>    free (arg_positions);
>  }
> +
> +/* Callback function to determine whether an expression TP or one of its
> +   subexpressions comes from macro expansion.  Used to suppress bogus
> +   warnings.  */
> +
> +static tree
> +expr_from_macro_expansion_r (tree *tp, int *, void *)
> +{
> +  if (CAN_HAVE_LOCATION_P (*tp)
> +      && from_macro_expansion_at (EXPR_LOCATION (*tp)))
> +    return integer_zero_node;
> +
> +  return NULL_TREE;
> +}
> +
> +/* Possibly warn when an if-else has identical branches.  */
> +
> +static void
> +do_warn_duplicated_branches (tree expr)
> +{
> +  tree thenb = COND_EXPR_THEN (expr);
> +  tree elseb = COND_EXPR_ELSE (expr);
> +
> +  /* Don't bother if there's no else branch.  */
> +  if (elseb == NULL_TREE)
> +    return;
> +
> +  /* And don't warn for empty statements.  */
> +  if (TREE_CODE (thenb) == NOP_EXPR
> +      && TREE_TYPE (thenb) == void_type_node
> +      && TREE_OPERAND (thenb, 0) == size_zero_node)
> +    return;
> +
> +  /* ... or empty branches.  */
> +  if (TREE_CODE (thenb) == STATEMENT_LIST
> +      && STATEMENT_LIST_HEAD (thenb) == NULL)
> +    return;
> +
> +  /* Compute the hash of the then branch.  */
> +  inchash::hash hstate0 (0);
> +  inchash::add_expr (thenb, hstate0);
> +  hashval_t h0 = hstate0.end ();
> +
> +  /* Compute the hash of the else branch.  */
> +  inchash::hash hstate1 (0);
> +  inchash::add_expr (elseb, hstate1);
> +  hashval_t h1 = hstate1.end ();
> +
> +  /* Compare the hashes.  */
> +  if (h0 == h1
> +      && operand_equal_p (thenb, elseb, OEP_LEXICOGRAPHIC)
> +      /* Don't warn if any of the branches or their subexpressions comes
> +      from a macro.  */
> +      && !walk_tree_without_duplicates (&thenb, expr_from_macro_expansion_r,
> +                                     NULL)
> +      && !walk_tree_without_duplicates (&elseb, expr_from_macro_expansion_r,
> +                                     NULL))
> +    warning_at (EXPR_LOCATION (expr), OPT_Wduplicated_branches,
> +             "this condition has identical branches");
> +}
> +
> +/* Callback for c_genericize to implement -Wduplicated-branches.  */
> +
> +tree
> +do_warn_duplicated_branches_r (tree *tp, int *, void *)
> +{
> +  if (TREE_CODE (*tp) == COND_EXPR)
> +    do_warn_duplicated_branches (*tp);
> +  return NULL_TREE;
> +}
> diff --git gcc/c-family/c.opt gcc/c-family/c.opt
> index 0b74aba..4b86695 100644
> --- gcc/c-family/c.opt
> +++ gcc/c-family/c.opt
> @@ -468,6 +468,10 @@ Wdiv-by-zero
>  C ObjC C++ ObjC++ Var(warn_div_by_zero) Init(1) Warning
>  Warn about compile-time integer division by zero.
>  
> +Wduplicated-branches
> +C ObjC C++ ObjC++ Var(warn_duplicated_branches) Init(0) Warning
> +Warn about duplicated branches in if-else statements.
> +
>  Wduplicated-cond
>  C ObjC C++ ObjC++ Var(warn_duplicated_cond) Init(0) Warning
>  Warn about duplicated conditions in an if-else-if chain.
> diff --git gcc/c/c-typeck.c gcc/c/c-typeck.c
> index 96e7351..ed8ffe4 100644
> --- gcc/c/c-typeck.c
> +++ gcc/c/c-typeck.c
> @@ -5193,6 +5193,15 @@ build_conditional_expr (location_t colon_loc, tree 
> ifexp, bool ifexp_bcp,
>      ret = build1 (EXCESS_PRECISION_EXPR, semantic_result_type, ret);
>  
>    protected_set_expr_location (ret, colon_loc);
> +
> +  /* If the OP1 and OP2 are the same and don't have side-effects,
> +     warn here, because the COND_EXPR will be turned into OP1.  */
> +  if (warn_duplicated_branches
> +      && TREE_CODE (ret) == COND_EXPR
> +      && (op1 == op2 || operand_equal_p (op1, op2, 0)))
> +    warning_at (EXPR_LOCATION (ret), OPT_Wduplicated_branches,
> +             "this condition has identical branches");
> +
>    return ret;
>  }
>  
> diff --git gcc/cp/call.c gcc/cp/call.c
> index e431221..84931fb 100644
> --- gcc/cp/call.c
> +++ gcc/cp/call.c
> @@ -5302,6 +5302,13 @@ build_conditional_expr_1 (location_t loc, tree arg1, 
> tree arg2, tree arg3,
>   valid_operands:
>    result = build3_loc (loc, COND_EXPR, result_type, arg1, arg2, arg3);
>  
> +  /* If the ARG2 and ARG3 are the same and don't have side-effects,
> +     warn here, because the COND_EXPR will be turned into ARG2.  */
> +  if (warn_duplicated_branches
> +      && (arg2 == arg3 || operand_equal_p (arg2, arg3, 0)))
> +    warning_at (EXPR_LOCATION (result), OPT_Wduplicated_branches,
> +             "this condition has identical branches");
> +
>    /* We can't use result_type below, as fold might have returned a
>       throw_expr.  */
>  
> diff --git gcc/cp/semantics.c gcc/cp/semantics.c
> index 2ab0723..49999ca 100644
> --- gcc/cp/semantics.c
> +++ gcc/cp/semantics.c
> @@ -670,6 +670,7 @@ tree
>  finish_expr_stmt (tree expr)
>  {
>    tree r = NULL_TREE;
> +  location_t loc = EXPR_LOCATION (expr);
>  
>    if (expr != NULL_TREE)
>      {
> @@ -694,7 +695,7 @@ finish_expr_stmt (tree expr)
>        if (TREE_CODE (expr) != CLEANUP_POINT_EXPR)
>       {
>         if (TREE_CODE (expr) != EXPR_STMT)
> -         expr = build_stmt (input_location, EXPR_STMT, expr);
> +         expr = build_stmt (loc, EXPR_STMT, expr);
>         expr = maybe_cleanup_point_expr_void (expr);
>       }
>  
> diff --git gcc/doc/invoke.texi gcc/doc/invoke.texi
> index 83ac135..845c708 100644
> --- gcc/doc/invoke.texi
> +++ gcc/doc/invoke.texi
> @@ -271,7 +271,8 @@ Objective-C and Objective-C++ Dialects}.
>  -Wno-deprecated -Wno-deprecated-declarations -Wno-designated-init @gol
>  -Wdisabled-optimization @gol
>  -Wno-discarded-qualifiers -Wno-discarded-array-qualifiers @gol
> --Wno-div-by-zero -Wdouble-promotion -Wduplicated-cond @gol
> +-Wno-div-by-zero -Wdouble-promotion -Wduplicated-branches @gol
> +-Wduplicated-cond @gol
>  -Wempty-body  -Wenum-compare  -Wno-endif-labels -Wexpansion-to-defined @gol
>  -Werror  -Werror=* -Wfatal-errors -Wfloat-equal  -Wformat  -Wformat=2 @gol
>  -Wno-format-contains-nul -Wno-format-extra-args -Wformat-length=@var{n} @gol
> @@ -3726,7 +3727,7 @@ Options} and @ref{Objective-C and Objective-C++ Dialect 
> Options}.
>  -Warray-bounds=1 @r{(only with} @option{-O2}@r{)}  @gol
>  -Wbool-compare  @gol
>  -Wbool-operation  @gol
> --Wc++11-compat  -Wc++14-compat@gol
> +-Wc++11-compat  -Wc++14-compat  @gol
>  -Wchar-subscripts  @gol
>  -Wcomment  @gol
>  -Wduplicate-decl-specifier @r{(C and Objective-C only)} @gol
> @@ -5229,6 +5230,22 @@ Incrementing a boolean is invalid in C++1z, and 
> deprecated otherwise.)
>  
>  This warning is enabled by @option{-Wall}.
>  
> +@item -Wduplicated-branches
> +@opindex Wno-duplicated-branches
> +@opindex Wduplicated-branches
> +Warn when an if-else has indentical branches.  This warning detects cases 
> like
> +@smallexample
> +if (p != NULL)
> +  return 0;
> +else
> +  return 0;
> +@end smallexample
> +It doesn't warn when both branches contain just a null statement.  This 
> warning
> +also warn for conditional operators:
> +@smallexample
> +  int i = x ? *p : *p;
> +@end smallexample
> +
>  @item -Wduplicated-cond
>  @opindex Wno-duplicated-cond
>  @opindex Wduplicated-cond
> diff --git gcc/fold-const.c gcc/fold-const.c
> index 73ebd76..b5375a8 100644
> --- gcc/fold-const.c
> +++ gcc/fold-const.c
> @@ -2722,6 +2722,9 @@ combine_comparisons (location_t loc,
>     If OEP_ADDRESS_OF is set, we are actually comparing addresses of objects,
>     not values of expressions.
>  
> +   If OEP_LEXICOGRAPHIC is set, then also handle expressions such as
> +   MODIFY_EXPR, RETURN_EXPR, as well as STATEMENT_LISTs.
> +
>     Unless OEP_MATCH_SIDE_EFFECTS is set, the function returns false on
>     any operand with side effect.  This is unnecesarily conservative in the
>     case we know that arg0 and arg1 are in disjoint code paths (such as in
> @@ -3154,6 +3157,23 @@ operand_equal_p (const_tree arg0, const_tree arg1, 
> unsigned int flags)
>       case BIT_INSERT_EXPR:
>         return OP_SAME (0) && OP_SAME (1) && OP_SAME (2);
>  
> +     case MODIFY_EXPR:
> +     case INIT_EXPR:
> +     case COMPOUND_EXPR:
> +     case PREDECREMENT_EXPR:
> +     case PREINCREMENT_EXPR:
> +     case POSTDECREMENT_EXPR:
> +     case POSTINCREMENT_EXPR:
> +       if (flags & OEP_LEXICOGRAPHIC)
> +         return OP_SAME (0) && OP_SAME (1);
> +       return 0;
> +
> +     case CLEANUP_POINT_EXPR:
> +     case EXPR_STMT:
> +       if (flags & OEP_LEXICOGRAPHIC)
> +         return OP_SAME (0);
> +       return 0;
> +
>       default:
>         return 0;
>       }
> @@ -3190,7 +3210,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, 
> unsigned int flags)
>             cef &= ECF_CONST | ECF_PURE;
>           else
>             cef &= ECF_CONST;
> -         if (!cef)
> +         if (!cef && !(flags & OEP_LEXICOGRAPHIC))
>             return 0;
>         }
>  
> @@ -3269,8 +3289,39 @@ operand_equal_p (const_tree arg0, const_tree arg1, 
> unsigned int flags)
>           }
>         return 1;
>       }
> +      else if (TREE_CODE (arg0) == STATEMENT_LIST
> +            && (flags & OEP_LEXICOGRAPHIC))
> +     {
> +       /* Compare the STATEMENT_LISTs.  */
> +       tree_stmt_iterator tsi1, tsi2;
> +       tree body1 = CONST_CAST_TREE (arg0);
> +       tree body2 = CONST_CAST_TREE (arg1);
> +       for (tsi1 = tsi_start (body1), tsi2 = tsi_start (body2); ;
> +            tsi_next (&tsi1), tsi_next (&tsi2))
> +         {
> +           /* The lists don't have the same number of statements.  */
> +           if (tsi_end_p (tsi1) ^ tsi_end_p (tsi2))
> +             return 0;
> +           if (tsi_end_p (tsi1) && tsi_end_p (tsi2))
> +             return 1;
> +           if (!operand_equal_p (tsi_stmt (tsi1), tsi_stmt (tsi2),
> +                                 OEP_LEXICOGRAPHIC))
> +             return 0;
> +         }
> +     }
>        return 0;
>  
> +    case tcc_statement:
> +      switch (TREE_CODE (arg0))
> +     {
> +     case RETURN_EXPR:
> +       if (flags & OEP_LEXICOGRAPHIC)
> +         return OP_SAME_WITH_NULL (0);
> +       return 0;
> +     default:
> +       return 0;
> +      }
> +
>      default:
>        return 0;
>      }
> @@ -13896,7 +13947,7 @@ fold_build_cleanup_point_expr (tree type, tree expr)
>          return expr;
>      }
>  
> -  return build1 (CLEANUP_POINT_EXPR, type, expr);
> +  return build1_loc (EXPR_LOCATION (expr), CLEANUP_POINT_EXPR, type, expr);
>  }
>  
>  /* Given a pointer value OP0 and a type TYPE, return a simplified version
> diff --git gcc/testsuite/c-c++-common/Wduplicated-branches-1.c 
> gcc/testsuite/c-c++-common/Wduplicated-branches-1.c
> index e69de29..c0b93fc 100644
> --- gcc/testsuite/c-c++-common/Wduplicated-branches-1.c
> +++ gcc/testsuite/c-c++-common/Wduplicated-branches-1.c
> @@ -0,0 +1,187 @@
> +/* PR c/64279 */
> +/* { dg-do compile } */
> +/* { dg-options "-Wduplicated-branches -O2" } */
> +
> +extern void foo (int);
> +extern int g;
> +extern int a[10];
> +
> +int
> +f (int i, int *p)
> +{
> +  const int j = 0;
> +  if (j == 0)
> +    {
> +      if (i > 10) /* { dg-warning "this condition has identical branches" } 
> */
> +     /* Optimizers can figure out that this is 1.  */
> +     *p = j * 2 + 1;
> +      else
> +     *p = 1;
> +    }
> +
> +  if (i)
> +    ;
> +  else
> +    ;
> +
> +  if (i == 0) /* { dg-warning "this condition has identical branches" } */
> +    return 0;
> +  else
> +    return 0;
> +
> +  if (i == 1) /* { dg-warning "this condition has identical branches" } */
> +    {
> +      g = 10;
> +    }
> +  else
> +    {
> +      g = 10;
> +    }
> +
> +  const char *s;
> +  if (i == 2) /* { dg-warning "this condition has identical branches" } */
> +    s = "foo";
> +  else
> +    s = "foo";
> +
> +  if (i == 3) /* { dg-warning "this condition has identical branches" } */
> +    g = a[i];
> +  else
> +    g = a[i];
> +
> +  if (i == 4) /* { dg-warning "this condition has identical branches" } */
> +    return i ? 1 : g;
> +  else
> +    return i ? 1 : g;
> +
> +  if (i == 5) /* { dg-warning "this condition has identical branches" } */
> +    {
> +      {
> +     {
> +       {
> +         g++;
> +       }
> +     }
> +      }
> +    }
> +  else
> +    {
> +      {
> +     {
> +       {
> +         g++;
> +       }
> +     }
> +      }
> +    }
> +
> +  if (i == 6) /* { dg-warning "this condition has identical branches" } */
> +    g = i * 6;
> +  else
> +    g = i * 6;
> +
> +  /* Don't warn.  */
> +  if (i == 7)
> +    g = i / 6;
> +  else
> +    g = 6 / i;
> +
> +  if (i == 8) /* { dg-warning "this condition has identical branches" } */
> +    return i * 8 * i * 8;
> +  else
> +    return 8 * i * 8 * i;
> +
> +
> +  if (i == 9) /* { dg-warning "this condition has identical branches" } */
> +    {
> +      p++;
> +      return *p;
> +    }
> +  else
> +    {
> +      p++;
> +      return *p;
> +    }
> +
> +  /* Don't warn.  */
> +  if (i == 10)
> +    return *++p;
> +  else
> +    return ++*p;
> +
> +  if (i == 11) /* { dg-warning "this condition has identical branches" } */
> +    {
> +      foo (6);
> +    }
> +  else
> +    {
> +      foo (6);
> +    }
> +
> +  if (i == 12) /* { dg-warning "this condition has identical branches" } */
> +    {
> +      foo (6 + i), foo (2);
> +    }
> +  else
> +    {
> +      foo (6 + i), foo (2);
> +    }
> +
> +  if (i == 13) /* { dg-warning "this condition has identical branches" } */
> +    p += (g + 1);
> +  else
> +    p += (g + 1);
> +
> +  if (i == 14) /* { dg-warning "this condition has identical branches" } */
> +    {
> +      foo (7);
> +      *p = 0;
> +      foo (9);
> +    }
> +  else
> +    {
> +      foo (7);
> +      *p = 0;
> +      foo (9);
> +    }
> +
> +  if (i == 15) /* { dg-warning "this condition has identical branches" } */
> +    p += (g + (1 + 2));
> +  else
> +    p += (g + (1 + 1 + 1));
> +
> +  if (i == 16) /* { dg-warning "this condition has identical branches" } */
> +    foo (10 + g);
> +  else
> +    foo (g + 10);
> +
> +  if (i == 17) /* { dg-warning "this condition has identical branches" } */
> +    ({ foo (i); });
> +  else
> +    ({ foo (i); });
> +
> +  if (i == 18)
> +    {
> +      if (i == 19)
> +     {
> +       if (i == 20) /* { dg-warning "this condition has identical branches" 
> } */
> +         foo (++i);
> +       else
> +         foo (++i);
> +     }
> +    }
> +
> +  /* Don't warn.  */
> +  if (i == 21)
> +    {
> +      foo (1);
> +      foo (2);
> +    }
> +  else
> +    {
> +      foo (2);
> +      foo (1);
> +    }
> +
> +  return 0;
> +}
> diff --git gcc/testsuite/c-c++-common/Wduplicated-branches-10.c 
> gcc/testsuite/c-c++-common/Wduplicated-branches-10.c
> index e69de29..8d918ef 100644
> --- gcc/testsuite/c-c++-common/Wduplicated-branches-10.c
> +++ gcc/testsuite/c-c++-common/Wduplicated-branches-10.c
> @@ -0,0 +1,18 @@
> +/* PR c/64279 */
> +/* { dg-do compile } */
> +/* { dg-options "-Wduplicated-branches" } */
> +
> +#define DEBUG(msg) ;
> +
> +void
> +f (int i)
> +{
> +  if (i > 9)
> +    {
> +      DEBUG ("foo");
> +    }
> +  else
> +    {
> +      DEBUG ("bar");
> +    }
> +}
> diff --git gcc/testsuite/c-c++-common/Wduplicated-branches-11.c 
> gcc/testsuite/c-c++-common/Wduplicated-branches-11.c
> index e69de29..70d86cf 100644
> --- gcc/testsuite/c-c++-common/Wduplicated-branches-11.c
> +++ gcc/testsuite/c-c++-common/Wduplicated-branches-11.c
> @@ -0,0 +1,75 @@
> +/* PR c/64279 */
> +/* { dg-do compile } */
> +/* { dg-options "-Wduplicated-branches" } */
> +
> +int
> +f (int p)
> +{
> +  if (p == 0)
> +    {
> +      p += 1, ++p;
> +    }
> +  else
> +    {
> +      p -= 1, ++p;
> +    }
> +
> +  if (p == 1)
> +    {
> +    }
> +  else
> +    p++;
> +
> +  if (p == 2)
> +    p++;
> +  else
> +    {
> +    }
> +
> +  if (p == 3)
> +    {
> +    }
> +  else
> +    {
> +    }
> +
> +  if (p == 4)
> +    {
> +      ++p;
> +      return p;
> +    }
> +  else
> +    {
> +      p++;
> +      return p;
> +    }
> +
> +  if (p == 5)
> +    ++p;
> +  else
> +    p++;
> +
> +  if (p == 6)
> +    {
> +      ++p;
> +      ++p;
> +      return p;
> +    }
> +  else
> +    {
> +      ++p;
> +      return p;
> +    }
> +
> +  if (p == 7)
> +    {
> +      ++p;
> +      return p;
> +    }
> +  else
> +    {
> +      ++p;
> +      ++p;
> +      return p;
> +    }
> +}
> diff --git gcc/testsuite/c-c++-common/Wduplicated-branches-12.c 
> gcc/testsuite/c-c++-common/Wduplicated-branches-12.c
> index e69de29..cd746f1 100644
> --- gcc/testsuite/c-c++-common/Wduplicated-branches-12.c
> +++ gcc/testsuite/c-c++-common/Wduplicated-branches-12.c
> @@ -0,0 +1,16 @@
> +/* PR c/64279 */
> +/* { dg-do compile } */
> +/* { dg-options "-Wduplicated-branches" } */
> +
> +void
> +f (int i)
> +{
> +  if (i) /* { dg-warning "this condition has identical branches" } */
> +    return 0;
> +/* { dg-warning ".return. with a value" "" { target c } .-1 } */
> +/* { dg-error "return-statement with a value" "" { target c++ } .-2 } */
> +  else
> +   return 0;
> +/* { dg-warning ".return. with a value" "" { target c } .-1 } */
> +/* { dg-error "return-statement with a value" "" { target c++ } .-2 } */
> +}
> diff --git gcc/testsuite/c-c++-common/Wduplicated-branches-2.c 
> gcc/testsuite/c-c++-common/Wduplicated-branches-2.c
> index e69de29..8669dd6 100644
> --- gcc/testsuite/c-c++-common/Wduplicated-branches-2.c
> +++ gcc/testsuite/c-c++-common/Wduplicated-branches-2.c
> @@ -0,0 +1,114 @@
> +/* PR c/64279 */
> +/* { dg-do compile } */
> +/* { dg-options "-Wduplicated-branches -O2" } */
> +
> +void
> +f (int *p)
> +{
> +  if (*p > 0)
> +    {
> +      if (x == 0) /* { dg-error "undeclared|not declared" } */
> +     *p = 5;
> +      else
> +     *p = 6;
> +    }
> +}
> +
> +void
> +f2 (int *p)
> +{
> +  if (*p > 0)
> +    {
> +      if (*p > 2)
> +     *p = x; /* { dg-error "undeclared|not declared" } */
> +      else
> +     *p = 6;
> +    }
> +}
> +
> +void
> +f3 (int *p)
> +{
> +  if (*p > 0)
> +    {
> +      if (*p > 2)
> +     *p = 8;
> +      else
> +     *p = x; /* { dg-error "undeclared|not declared" } */
> +    }
> +}
> +
> +void
> +f4 (int *p)
> +{
> +  if (*p > 0)
> +    {
> +      if (x == 0) /* { dg-error "undeclared|not declared" } */
> +     *p = 5;
> +      else
> +     *p = 6;
> +    }
> +  else
> +    {
> +      if (x == 0) /* { dg-error "not declared" "" { target c++ } } */
> +     *p = 7;
> +      else
> +     *p = 6;
> +    }
> +}
> +
> +void
> +f5 (int *p)
> +{
> +  if (*p > 0)
> +    {
> +      if (*p > 2)
> +     *p = x; /* { dg-error "undeclared|not declared" } */
> +      else
> +     *p = 6;
> +    }
> +  else
> +    {
> +      if (x == 0) /* { dg-error "not declared" "" { target c++ } } */
> +     *p = 5;
> +      else
> +     *p = 6;
> +    }
> +}
> +
> +void
> +f6 (int *p)
> +{
> +  if (*p > 0)
> +    {
> +      if (*p > 2)
> +     *p = 8;
> +      else
> +     *p = x; /* { dg-error "undeclared|not declared" } */
> +    }
> +  else
> +    {
> +      if (x == 0) /* { dg-error "not declared" "" { target c++ } } */
> +     *p = 5;
> +      else
> +     *p = 6;
> +    }
> +}
> +
> +void
> +f7 (int i)
> +{
> +  if (i > 5)
> +    ({ x++; }); /* { dg-error "undeclared|not declared" } */
> +  else
> +    ({ i++; });
> +}
> +
> +void
> +f8 (int i)
> +{
> +  if (i > 5)
> +    ({ i++; });
> +  else
> +    ({ x++; }); /* { dg-error "undeclared|not declared" } */
> +}
> diff --git gcc/testsuite/c-c++-common/Wduplicated-branches-3.c 
> gcc/testsuite/c-c++-common/Wduplicated-branches-3.c
> index e69de29..e188384 100644
> --- gcc/testsuite/c-c++-common/Wduplicated-branches-3.c
> +++ gcc/testsuite/c-c++-common/Wduplicated-branches-3.c
> @@ -0,0 +1,19 @@
> +/* PR c/64279 */
> +/* { dg-do compile } */
> +/* { dg-options "-Wduplicated-branches" } */
> +
> +extern int *g;
> +
> +void
> +f (short int i)
> +{
> +  if (i == 0) /* { dg-warning "this condition has identical branches" } */
> +    *g = (int) i;
> +  else
> +    *g = (int) i;
> +
> +  if (i == 1)
> +    *g = (unsigned char) i;
> +  else
> +    *g = (signed char) i;
> +}
> diff --git gcc/testsuite/c-c++-common/Wduplicated-branches-4.c 
> gcc/testsuite/c-c++-common/Wduplicated-branches-4.c
> index e69de29..79af549 100644
> --- gcc/testsuite/c-c++-common/Wduplicated-branches-4.c
> +++ gcc/testsuite/c-c++-common/Wduplicated-branches-4.c
> @@ -0,0 +1,35 @@
> +/* PR c/64279 */
> +/* { dg-do compile } */
> +/* { dg-options "-Wduplicated-branches" } */
> +
> +extern int *g;
> +extern const int *q;
> +
> +void
> +f (int i)
> +{
> +  int j;
> +
> +  if (i == 0)
> +    for (j = 0; j < 10; j++)
> +       ++*g;
> +  else
> +    for (j = 0; j < 10; j++)
> +       ++*g;
> +
> +  if (i == 1)
> +    {
> +      int i = 10;
> +      *g = i;
> +    }
> +  else
> +    {
> +      int i = 10;
> +      *g = i;
> +    }
> +
> +  if (i == 3)
> +    q = (const int []){1};
> +  else
> +    q = (const int []){1};
> +}
> diff --git gcc/testsuite/c-c++-common/Wduplicated-branches-5.c 
> gcc/testsuite/c-c++-common/Wduplicated-branches-5.c
> index e69de29..f2eb8ec 100644
> --- gcc/testsuite/c-c++-common/Wduplicated-branches-5.c
> +++ gcc/testsuite/c-c++-common/Wduplicated-branches-5.c
> @@ -0,0 +1,24 @@
> +/* PR c/64279 */
> +/* { dg-do compile } */
> +/* { dg-options "-Wduplicated-branches" } */
> +
> +extern int g;
> +extern void foo ();
> +#define A g = i
> +#define B g = i
> +#define DOIT() foo()
> +#define DOIT2() foo()
> +
> +void
> +f (int i)
> +{
> +  if (i == 0)
> +    A;
> +  else
> +    B;
> +
> +  if (i == 1)
> +    DOIT();
> +  else
> +    DOIT2();
> +}
> diff --git gcc/testsuite/c-c++-common/Wduplicated-branches-6.c 
> gcc/testsuite/c-c++-common/Wduplicated-branches-6.c
> index e69de29..0010693 100644
> --- gcc/testsuite/c-c++-common/Wduplicated-branches-6.c
> +++ gcc/testsuite/c-c++-common/Wduplicated-branches-6.c
> @@ -0,0 +1,12 @@
> +/* PR c/64279 */
> +/* { dg-do compile } */
> +/* { dg-options "-Wduplicated-branches" } */
> +
> +void
> +f (int i)
> +{
> +  if (i == 0)
> +    ;
> +  else if (i == 1)
> +    ;
> +}
> diff --git gcc/testsuite/c-c++-common/Wduplicated-branches-7.c 
> gcc/testsuite/c-c++-common/Wduplicated-branches-7.c
> index e69de29..03721dc 100644
> --- gcc/testsuite/c-c++-common/Wduplicated-branches-7.c
> +++ gcc/testsuite/c-c++-common/Wduplicated-branches-7.c
> @@ -0,0 +1,36 @@
> +/* PR c/64279 */
> +/* { dg-do compile } */
> +/* { dg-options "-Wduplicated-branches" } */
> +
> +struct S
> +{
> +  int x;
> +} s;
> +int a[10];
> +
> +#define XMEM(R) ((R).x)
> +#define XSTR(R) ((R).x)
> +
> +void
> +f (int i)
> +{
> +  if (i)
> +    XMEM(s) = 1;
> +  else
> +    XSTR(s) = 1;
> +
> +  if (i) /* { dg-warning "this condition has identical branches" } */
> +    s.x = 1;
> +  else
> +    s.x = 1;
> +
> +  if (i)
> +    XMEM(s) = 1;
> +  else
> +    s.x = 1;
> +
> +  if (i)
> +    s.x = 1;
> +  else
> +    XMEM(s) = 1;
> +}
> diff --git gcc/testsuite/c-c++-common/Wduplicated-branches-8.c 
> gcc/testsuite/c-c++-common/Wduplicated-branches-8.c
> index e69de29..c5e8ca0 100644
> --- gcc/testsuite/c-c++-common/Wduplicated-branches-8.c
> +++ gcc/testsuite/c-c++-common/Wduplicated-branches-8.c
> @@ -0,0 +1,73 @@
> +/* PR c/64279 */
> +/* { dg-do compile } */
> +/* { dg-options "-Wduplicated-branches" } */
> +
> +#define A 5
> +#define B 5
> +#define I i
> +extern int a[10];
> +extern int g;
> +
> +int
> +f (int i)
> +{
> +  if (i == 1) /* { dg-warning "this condition has identical branches" } */
> +   return a[5];
> +  else
> +   return a[5];
> +
> +  if (i == 2) /* { dg-bogus "this condition has identical branches" "" { 
> xfail *-*-* } } */
> +   return a[A];
> +  else
> +   return a[5];
> +
> +  if (i == 3) /* { dg-bogus "this condition has identical branches" "" { 
> xfail *-*-* } } */
> +   return a[5];
> +  else
> +   return a[A];
> +
> +  if (i == 4) /* { dg-warning "this condition has identical branches" } */
> +   return a[A];
> +  else
> +   return a[A];
> +
> +  if (i == 5) /* { dg-warning "this condition has identical branches" } */
> +   return a[i];
> +  else
> +   return a[i];
> +
> +  if (i == 6) /* { dg-bogus "this condition has identical branches" "" { 
> xfail *-*-* } } */
> +   return a[I];
> +  else
> +   return a[i];
> +
> +  if (i == 7) /* { dg-bogus "this condition has identical branches" "" { 
> xfail *-*-* } } */
> +   return a[i];
> +  else
> +   return a[I];
> +
> +  if (i == 8) /* { dg-warning "this condition has identical branches" } */
> +   return a[I];
> +  else
> +   return a[I];
> +
> +  if (i == 10) /* { dg-bogus "this condition has identical branches" "" { 
> xfail *-*-* } } */
> +    g += A;
> +  else
> +    g += B;
> +
> +  if (i == 11) /* { dg-bogus "this condition has identical branches" "" { 
> xfail *-*-* } } */
> +    g += B;
> +  else
> +    g += A;
> +
> +  if (i == 12) /* { dg-bogus "this condition has identical branches" "" { 
> xfail *-*-* } } */
> +    g += A;
> +  else
> +    g += 5;
> +
> +  if (i == 12) /* { dg-bogus "this condition has identical branches" "" { 
> xfail *-*-* } } */
> +    g += 5;
> +  else
> +    g += A;
> +}
> diff --git gcc/testsuite/c-c++-common/Wduplicated-branches-9.c 
> gcc/testsuite/c-c++-common/Wduplicated-branches-9.c
> index e69de29..9b21776 100644
> --- gcc/testsuite/c-c++-common/Wduplicated-branches-9.c
> +++ gcc/testsuite/c-c++-common/Wduplicated-branches-9.c
> @@ -0,0 +1,46 @@
> +/* PR c/64279 */
> +/* { dg-do compile } */
> +/* { dg-options "-Wduplicated-branches" } */
> +
> +extern int *p, foo (void), a[10];
> +#define N 5
> +#define M 5
> +#define I i
> +
> +void
> +f (int i)
> +{
> +  *p += i ? 1 : 1; /* { dg-warning "this condition has identical branches" } 
> */
> +  *p += i ? N : M; /* { dg-bogus "this condition has identical branches" "" 
> { xfail *-*-* } } */
> +  *p += i ? M : N; /* { dg-bogus "this condition has identical branches" "" 
> { xfail *-*-* } } */
> +  *p += i ? i : i; /* { dg-warning "this condition has identical branches" } 
> */
> +  *p += i ? i++ : i++; /* { dg-warning "this condition has identical 
> branches" } */
> +  *p += i ? foo () : foo (); /* { dg-warning "this condition has identical 
> branches" } */
> +  *p += i ? ({ i++; }) : ({ i++; }); /* { dg-warning "this condition has 
> identical branches" } */
> +  *p += i ? a[i] : a[i]; /* { dg-warning "this condition has identical 
> branches" } */
> +  *p += i ? a[5] : a[5]; /* { dg-warning "this condition has identical 
> branches" } */
> +  *p += i ? a[N] : a[M]; /* { dg-bogus "this condition has identical 
> branches" "" { xfail *-*-* } } */
> +  *p += i ? a[5] : a[M]; /* { dg-bogus "this condition has identical 
> branches" "" { xfail *-*-* } } */
> +  *p += i ? a[M] : a[5]; /* { dg-bogus "this condition has identical 
> branches" "" { xfail *-*-* } } */
> +  *p += i ? a[I] : a[I]; /* { dg-warning "this condition has identical 
> branches" } */
> +  *p += i ? a[i] : a[I]; /* { dg-bogus "this condition has identical 
> branches" "" { xfail *-*-* } } */
> +  *p += i ? a[I] : a[i]; /* { dg-bogus "this condition has identical 
> branches" "" { xfail *-*-* } } */
> +
> +  *p += i ?: 1;
> +  *p += i ?: M;
> +  *p += i ?: N;
> +  *p += i ?: i; /* { dg-warning "this condition has identical branches" "" { 
> target c++ } } */
> +  *p += i ?: i++;
> +  *p += i ?: foo ();
> +  *p += i ?: ({ i++; });
> +  *p += i ?: a[i];
> +  *p += i ?: a[5];
> +  *p += i ?: a[M];
> +  *p += i ?: a[M];
> +  *p += i ?: a[5];
> +  *p += i ?: a[I];
> +  *p += i ?: a[I];
> +  *p += i ?: a[i];
> +
> +  *p += (i > 5 ? (i > 10 ? i : i) : i); /* { dg-warning "this condition has 
> identical branches" } */
> +}
> diff --git gcc/testsuite/c-c++-common/Wimplicit-fallthrough-7.c 
> gcc/testsuite/c-c++-common/Wimplicit-fallthrough-7.c
> index 21a158c..898e5fa 100644
> --- gcc/testsuite/c-c++-common/Wimplicit-fallthrough-7.c
> +++ gcc/testsuite/c-c++-common/Wimplicit-fallthrough-7.c
> @@ -39,9 +39,9 @@ f (int i)
>    switch (i)
>      {
>      case 1:
> -      do /* { dg-warning "statement may fall through" "" { target c++ } 42 } 
> */
> +      do
>       bar (2);
> -      while (--i); /* { dg-warning "statement may fall through" "" { target 
> c } 44 } */
> +      while (--i); /* { dg-warning "statement may fall through" } */
>      case 2:
>        bar (99);
>      }
> diff --git gcc/testsuite/g++.dg/cpp0x/lambda/lambda-switch.C 
> gcc/testsuite/g++.dg/cpp0x/lambda/lambda-switch.C
> index d71d3ad..ee87def 100644
> --- gcc/testsuite/g++.dg/cpp0x/lambda/lambda-switch.C
> +++ gcc/testsuite/g++.dg/cpp0x/lambda/lambda-switch.C
> @@ -16,11 +16,11 @@ main ()
>             break;            // { dg-error "break" }
>           }
>         };
> -       l = []()
> +       l = []()              // { dg-warning "statement will never be 
> executed" }
>           {
>           case 3:             // { dg-error "case" }
>             break;            // { dg-error "break" }
> -         };                  // { dg-warning "statement will never be 
> executed" }
> +         };
>       }
>      }
>  }
> diff --git gcc/testsuite/g++.dg/ext/builtin-object-size3.C 
> gcc/testsuite/g++.dg/ext/builtin-object-size3.C
> index 0207f9a..b2a9170 100644
> --- gcc/testsuite/g++.dg/ext/builtin-object-size3.C
> +++ gcc/testsuite/g++.dg/ext/builtin-object-size3.C
> @@ -3,7 +3,7 @@
>  
>  void baz (int *, int *);
>  
> -#define MEMCPY(d,s,l) __builtin___memcpy_chk (d, s, l, __builtin_object_size 
> (d, 0))
> +#define MEMCPY(d,s,l) __builtin___memcpy_chk (d, s, l, __builtin_object_size 
> (d, 0)) // { dg-warning "writing" }
>  
>  int
>  foo ()
> @@ -20,7 +20,7 @@ bar ()
>  {
>    int *p = new int;
>    int *q = new int[4];
> -  MEMCPY (p, "abcdefghijklmnopqrstuvwxyz", sizeof (int) + 1);                
> // { dg-warning "writing" }
> -  MEMCPY (q, "abcdefghijklmnopqrstuvwxyz", 4 * sizeof (int) + 1);    // { 
> dg-warning "writing" }
> +  MEMCPY (p, "abcdefghijklmnopqrstuvwxyz", sizeof (int) + 1); // { 
> dg-message "in expansion of macro" }
> +  MEMCPY (q, "abcdefghijklmnopqrstuvwxyz", 4 * sizeof (int) + 1); // { 
> dg-message "in expansion of macro" }
>    baz (p, q);
>  }
> diff --git gcc/testsuite/g++.dg/gomp/loop-1.C 
> gcc/testsuite/g++.dg/gomp/loop-1.C
> index de08eb3..b3db0f4 100644
> --- gcc/testsuite/g++.dg/gomp/loop-1.C
> +++ gcc/testsuite/g++.dg/gomp/loop-1.C
> @@ -82,8 +82,8 @@ f1 (int x)
>      for (j = i + 3; j < 16; j += 2) /* { dg-error "initializer expression 
> refers to iteration variable" } */
>        ;
>    #pragma omp for collapse(2)
> -  for (i = 0; i < 16; i++) /* { dg-error "initializer expression refers to 
> iteration variable" } */
> -    for (j = baz (&i); j < 16; j += 2)
> +  for (i = 0; i < 16; i++)
> +    for (j = baz (&i); j < 16; j += 2) /* { dg-error "initializer expression 
> refers to iteration variable" } */
>        ;
>    #pragma omp for collapse(2)
>    for (i = 0; i < 16; i++)
> @@ -215,8 +215,8 @@ f2 (int x)
>      for (int j = i + 3; j < 16; j += 2) /* { dg-error "initializer 
> expression refers to iteration variable" } */
>        ;
>    #pragma omp for collapse(2)
> -  for (int i = 0; i < 16; i++) /* { dg-error "initializer expression refers 
> to iteration variable" } */
> -    for (int j = baz (&i); j < 16; j += 2)
> +  for (int i = 0; i < 16; i++)
> +    for (int j = baz (&i); j < 16; j += 2) /* { dg-error "initializer 
> expression refers to iteration variable" } */
>        ;
>    #pragma omp for collapse(2)
>    for (int i = 0; i < 16; i++)
> diff --git gcc/testsuite/g++.dg/warn/Wduplicated-branches1.C 
> gcc/testsuite/g++.dg/warn/Wduplicated-branches1.C
> index e69de29..7ebd55e 100644
> --- gcc/testsuite/g++.dg/warn/Wduplicated-branches1.C
> +++ gcc/testsuite/g++.dg/warn/Wduplicated-branches1.C
> @@ -0,0 +1,21 @@
> +// PR c/64279
> +// { dg-do compile }
> +// { dg-options "-Wduplicated-branches" }
> +
> +template <typename T>
> +void
> +f (char i, int *p)
> +{
> +  if (i)
> +    *p = (signed short) i;
> +  else
> +    *p = (unsigned short) i;
> +
> +  if (i) // { dg-warning "this condition has identical branches" }
> +    *p = (T) i;
> +  else
> +    *p = (unsigned short) i;
> +}
> +
> +template void f<unsigned short>(char, int *); // { dg-message "required from 
> here" }
> +template void f<signed short>(char, int *);
> diff --git gcc/testsuite/g++.dg/warn/Wduplicated-branches2.C 
> gcc/testsuite/g++.dg/warn/Wduplicated-branches2.C
> index e69de29..4da2d54 100644
> --- gcc/testsuite/g++.dg/warn/Wduplicated-branches2.C
> +++ gcc/testsuite/g++.dg/warn/Wduplicated-branches2.C
> @@ -0,0 +1,8 @@
> +// PR c/6427
> +// { dg-do compile { target c++11 } }
> +// { dg-options "-Wduplicated-branches" }
> +
> +template<typename _ITp>
> +struct S {
> +  static constexpr int i = sizeof(_ITp) > alignof(_ITp) ? sizeof(_ITp) : 
> alignof(_ITp);
> +};
> diff --git gcc/tree-core.h gcc/tree-core.h
> index 37a52c3..6a02d28 100644
> --- gcc/tree-core.h
> +++ gcc/tree-core.h
> @@ -814,7 +814,9 @@ enum operand_equal_flag {
>    /* Internal within operand_equal_p:  */
>    OEP_NO_HASH_CHECK = 16,
>    /* Internal within inchash::add_expr:  */
> -  OEP_HASH_CHECK = 32
> +  OEP_HASH_CHECK = 32,
> +  /* Makes operand_equal_p handle more expressions:  */
> +  OEP_LEXICOGRAPHIC = 64
>  };
>  
>  /* Enum and arrays used for tree allocation stats.
> diff --git gcc/tree.c gcc/tree.c
> index 1934301..ddb9152 100644
> --- gcc/tree.c
> +++ gcc/tree.c
> @@ -7773,7 +7773,7 @@ add_expr (const_tree t, inchash::hash &hstate, unsigned 
> int flags)
>    enum tree_code code;
>    enum tree_code_class tclass;
>  
> -  if (t == NULL_TREE)
> +  if (t == NULL_TREE || t == error_mark_node)
>      {
>        hstate.merge_hash (0);
>        return;
> 
>       Marek
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 
21284 (AG Nuernberg)

Reply via email to