This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH RFA: -Wc++-compat warning about operator names
- From: Ian Lance Taylor <iant at google dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 12 Jun 2009 11:45:23 -0700
- Subject: PATCH RFA: -Wc++-compat warning about operator names
The -Wc++-compat option warns about the use of C++ reserved words, but
it does not warn about the use of C++ operator names. These are 11
special names like "and" which C++ must be treated as operators. For
example, "i and b" in C++ is equivalent to "i && b".
This patch modifies -Wc++-compat to also warn about these operator
names. This must be done in the preprocessor code, because the operator
names work in preprocessor # lines just as they do in regular code.
This patch also fixes the one case in the main gcc source code where a
C++ operator name is used as an identifier--some code in fold-const.c
uses a local variable named "and".
This requires approval from a C or C++ frontend maintainer.
Bootstrapped and tested on x86_64-unknown-linux-gnu. OK for mainline?
Ian
libcpp/ChangeLog:
2009-06-12 Ian Lance Taylor <iant@google.com>
* include/cpplib.h (struct cpp_options): Add
warn_cxx_operator_names field.
(NODE_WARN_OPERATOR): Define.
(struct cpp_hashnode): Increase flags field to 10 bits, decrease
type to 6 bits.
* init.c (mark_named_operators): Add flags parameter.
(cpp_post_options): Pick flags value to pass to
mark_named_operators.
* lex.c (lex_identifier): If NODE_WARN_OPERATOR is set, warn that
identifier is an operator name in C++.
gcc/ChangeLog:
2009-06-12 Ian Lance Taylor <iant@google.com>
* fold-const.c (fold_unary): Rename local variable and to
and_expr.
* c-opts.c (c_common_handle_option): For -Wc++-compat set
cpp_opts->warn_cxx_operator_names.
gcc/testsuite/ChangeLog:
2009-06-12 Ian Lance Taylor <iant@google.com>
* gcc.dg/Wcxx-compat-13.c: New testcase.
Index: libcpp/include/cpplib.h
===================================================================
--- libcpp/include/cpplib.h (revision 148327)
+++ libcpp/include/cpplib.h (working copy)
@@ -397,6 +397,9 @@ struct cpp_options
/* Nonzero means handle C++ alternate operator names. */
unsigned char operator_names;
+ /* Nonzero means warn about use of C++ alternate operator names. */
+ unsigned char warn_cxx_operator_names;
+
/* True for traditional preprocessing. */
unsigned char traditional;
@@ -555,7 +558,8 @@ extern const char *progname;
identifier that behaves like an operator such as "xor".
NODE_DIAGNOSTIC is for speed in lex_token: it indicates a
diagnostic may be required for this node. Currently this only
- applies to __VA_ARGS__ and poisoned identifiers. */
+ applies to __VA_ARGS__, poisoned identifiers, and -Wc++-compat
+ warnings about NODE_OPERATOR. */
/* Hash node flags. */
#define NODE_OPERATOR (1 << 0) /* C++ named operator. */
@@ -567,6 +571,7 @@ extern const char *progname;
#define NODE_MACRO_ARG (1 << 6) /* Used during #define processing. */
#define NODE_USED (1 << 7) /* Dumped with -dU. */
#define NODE_CONDITIONAL (1 << 8) /* Conditional macro */
+#define NODE_WARN_OPERATOR (1 << 9) /* Warn about C++ named operator. */
/* Different flavors of hash node. */
enum node_type
@@ -636,8 +641,8 @@ struct GTY(()) cpp_hashnode {
then index into directive table.
Otherwise, a NODE_OPERATOR. */
unsigned char rid_code; /* Rid code - for front ends. */
- ENUM_BITFIELD(node_type) type : 7; /* CPP node type. */
- unsigned int flags : 9; /* CPP flags. */
+ ENUM_BITFIELD(node_type) type : 6; /* CPP node type. */
+ unsigned int flags : 10; /* CPP flags. */
union _cpp_hashnode_value GTY ((desc ("CPP_HASHNODE_VALUE_IDX (%1)"))) value;
};
Index: libcpp/init.c
===================================================================
--- libcpp/init.c (revision 148327)
+++ libcpp/init.c (working copy)
@@ -28,7 +28,7 @@ along with this program; see the file CO
#include "localedir.h"
static void init_library (void);
-static void mark_named_operators (cpp_reader *);
+static void mark_named_operators (cpp_reader *, int);
static void read_original_filename (cpp_reader *);
static void read_original_directory (cpp_reader *);
static void post_options (cpp_reader *);
@@ -366,7 +366,7 @@ static const struct builtin_operator ope
/* Mark the C++ named operators in the hash table. */
static void
-mark_named_operators (cpp_reader *pfile)
+mark_named_operators (cpp_reader *pfile, int flags)
{
const struct builtin_operator *b;
@@ -375,7 +375,7 @@ mark_named_operators (cpp_reader *pfile)
b++)
{
cpp_hashnode *hp = cpp_lookup (pfile, b->name, b->len);
- hp->flags |= NODE_OPERATOR;
+ hp->flags |= flags;
hp->is_directive = 0;
hp->directive_index = b->value;
}
@@ -512,13 +512,20 @@ static void sanity_checks (cpp_reader *p
void
cpp_post_options (cpp_reader *pfile)
{
+ int flags;
+
sanity_checks (pfile);
post_options (pfile);
/* Mark named operators before handling command line macros. */
+ flags = 0;
if (CPP_OPTION (pfile, cplusplus) && CPP_OPTION (pfile, operator_names))
- mark_named_operators (pfile);
+ flags |= NODE_OPERATOR;
+ if (CPP_OPTION (pfile, warn_cxx_operator_names))
+ flags |= NODE_DIAGNOSTIC | NODE_WARN_OPERATOR;
+ if (flags != 0)
+ mark_named_operators (pfile, flags);
}
/* Setup for processing input from the file named FNAME, or stdin if
Index: libcpp/lex.c
===================================================================
--- libcpp/lex.c (revision 148327)
+++ libcpp/lex.c (working copy)
@@ -560,6 +560,12 @@ lex_identifier (cpp_reader *pfile, const
cpp_error (pfile, CPP_DL_PEDWARN,
"__VA_ARGS__ can only appear in the expansion"
" of a C99 variadic macro");
+
+ /* For -Wc++-compat, warn about use of C++ named operators. */
+ if (result->flags & NODE_WARN_OPERATOR)
+ cpp_error (pfile, CPP_DL_WARNING,
+ "identifier \"%s\" is a special operator name in C++",
+ NODE_NAME (result));
}
return result;
Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c (revision 148327)
+++ gcc/fold-const.c (working copy)
@@ -8290,13 +8290,14 @@ fold_unary (enum tree_code code, tree ty
&& TREE_CODE (op0) == BIT_AND_EXPR
&& TREE_CODE (TREE_OPERAND (op0, 1)) == INTEGER_CST)
{
- tree and = op0;
- tree and0 = TREE_OPERAND (and, 0), and1 = TREE_OPERAND (and, 1);
+ tree and_expr = op0;
+ tree and0 = TREE_OPERAND (and_expr, 0);
+ tree and1 = TREE_OPERAND (and_expr, 1);
int change = 0;
- if (TYPE_UNSIGNED (TREE_TYPE (and))
+ if (TYPE_UNSIGNED (TREE_TYPE (and_expr))
|| (TYPE_PRECISION (type)
- <= TYPE_PRECISION (TREE_TYPE (and))))
+ <= TYPE_PRECISION (TREE_TYPE (and_expr))))
change = 1;
else if (TYPE_PRECISION (TREE_TYPE (and1))
<= HOST_BITS_PER_WIDE_INT
Index: gcc/testsuite/gcc.dg/Wcxx-compat-13.c
===================================================================
--- gcc/testsuite/gcc.dg/Wcxx-compat-13.c (revision 0)
+++ gcc/testsuite/gcc.dg/Wcxx-compat-13.c (revision 0)
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-Wc++-compat" } */
+
+int and; /* { dg-warning "operator" } */
+int and_eq; /* { dg-warning "operator" } */
+int bitand; /* { dg-warning "operator" } */
+int bitor; /* { dg-warning "operator" } */
+int compl; /* { dg-warning "operator" } */
+int not; /* { dg-warning "operator" } */
+int not_eq; /* { dg-warning "operator" } */
+int or; /* { dg-warning "operator" } */
+int or_eq; /* { dg-warning "operator" } */
+int xor; /* { dg-warning "operator" } */
+int xor_eq; /* { dg-warning "operator" } */
+
+#define M1 and /* { dg-warning "operator" } */
+#define M2 and_eq /* { dg-warning "operator" } */
+#define M3 bitand /* { dg-warning "operator" } */
+#define M4 bitor /* { dg-warning "operator" } */
+#define M5 compl /* { dg-warning "operator" } */
+#define M6 not /* { dg-warning "operator" } */
+#define M7 not_eq /* { dg-warning "operator" } */
+#define M8 or /* { dg-warning "operator" } */
+#define M9 or_eq /* { dg-warning "operator" } */
+#define M10 xor /* { dg-warning "operator" } */
+#define M11 xor_eq /* { dg-warning "operator" } */
Index: gcc/c-opts.c
===================================================================
--- gcc/c-opts.c (revision 148327)
+++ gcc/c-opts.c (working copy)
@@ -445,6 +445,7 @@ c_common_handle_option (size_t scode, co
implies -Wenum-compare. */
if (warn_enum_compare == -1 && value)
warn_enum_compare = value;
+ cpp_opts->warn_cxx_operator_names = value;
break;
case OPT_Wdeprecated: