This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [C/C++] PR 13358 long long and C++ do not mix well


I think the following patch addresses all requirements and in the
process it fixes some small deficiencies of the current status, such
as talking about C99 when invoked from C++.

Bootstrapped and regression tested on x86_64-unknown-linux-gnu with
--enable-languages=all,obj-c++ --enable-decimal-float and
--target_board=\{-m32,-m64\}

OK for trunk?

2008-10-23  Manuel Lopez-Ibanez  <manu@gcc.gnu.org>

	PR 13358
	* doc/invoke.texi (-Wlong-long): Update description.
	* c-lex (interpret_integer): Only warn if there was no previous
	overflow and -Wlong-long is enabled.
	* c-decl.c (declspecs_add_type): Drop redundant flags.
	* c.opt (Wlong-long): Init to -1.
	* c-opts.c (sanitize_cpp_opts): Synchronize cpp's warn_long_long
	and front-end warn_long_long. Wlong-long only depends on other
	flags if it is uninitialized.
	* c-parser.c (disable_extension_diagnostics): warn_long_long is
	the same for CPP and FE.
	(restore_extension_diagnostics): Likewise.
libcpp/
	* init.c (cpp_create_reader): Wlong_long is disabled by default.
	* expr.c (cpp_classify_number): Give different messages for C and
	C++ front-ends.
cp/
	* parser.c (cp_parser_check_decl_spec): Drop redundant flags.
	* error.c (pedwarn_cxx98): New.
	* cp-tree.h (pedwarn_cxx98): Declare.
	
testsuite/
	* gcc.dg/wtr-int-type-1.c: Use two dg-warning to match two
	messages. Test for "long long" in system headers.
	* gcc.dg/c99-longlong-2.c: New.
	* g++.dg/warn/pr13358.C: New.
	* g++.dg/warn/pr13358-2.C: New.
	* g++.dg/warn/pr13358-3.C: New.
	* g++.dg/warn/pr13358-4.C: New.



2008/8/29 Manuel López-Ibáñez <lopezibanez@gmail.com>:
> 2008/8/29 Joseph S. Myers <joseph@codesourcery.com>:
>> On Fri, 29 Aug 2008, Manuel López-Ibáñez wrote:
>>
>>> CPP and the FE were using different semantics. invoke.texi said that
>>> Wlong-long was the default. This was not correct. It was the default
>>> for CPP but -Wno-long-long was the default for the FE. Now there is
>>> only one semantic: the one from the FE.
>>>
>>> However, we were inhibiting warning even if the user requested it
>>> through Wlong-long. Now explicit Wlong-long (or Wno-long-long)
>>> overrides everything else, except in system headers.
>>
>> If you allow -Wlong-long to have an effect in C99 mode, -std=c99
>> -pedantic-errors -Wlong-long should give the diagnostics as warnings not
>> errors.  Does it?
>
> No but I can make it do that just using pedwarn_c90 instead of pedwarn
> and add a testcase. I'll do the same for c++98. I''ll need to add an
> equivalent of pedwarn_c90 to C++ and CPP. In C++ is probably easy.
>
> Is there a way to tell in CPP if we are being called from the C++ FE?
> and which standard? I cannot find anything in the sources apart from
> CPP_OPTION (pfile, c99).
>
> Cheers,
>
> Manuel.
>
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 141265)
+++ gcc/doc/invoke.texi	(working copy)
@@ -4059,14 +4059,13 @@ Warn if a precompiled header (@pxref{Pre
 the search path but can't be used.
 
 @item -Wlong-long
 @opindex Wlong-long
 @opindex Wno-long-long
-Warn if @samp{long long} type is used.  This is default.  To inhibit
-the warning messages, use @option{-Wno-long-long}.  Flags
-@option{-Wlong-long} and @option{-Wno-long-long} are taken into account
-only when @option{-pedantic} flag is used.
+Warn if @samp{long long} type is used.  This is enabled by either
+@option{-pedantic} or @option{-Wtraditional} in ISO C90 and C++98
+modes.  To inhibit the warning messages, use @option{-Wno-long-long}.
 
 @item -Wvariadic-macros
 @opindex Wvariadic-macros
 @opindex Wno-variadic-macros
 Warn if variadic macros are used in pedantic ISO C90 mode, or the GNU
Index: gcc/c-lex.c
===================================================================
--- gcc/c-lex.c	(revision 141265)
+++ gcc/c-lex.c	(working copy)
@@ -580,17 +580,22 @@ interpret_integer (const cpp_token *toke
     /* cpplib has already issued a warning for overflow.  */
     type = ((flags & CPP_N_UNSIGNED)
 	    ? widest_unsigned_literal_type_node
 	    : widest_integer_literal_type_node);
   else
-    type = integer_types[itk];
-
-  if (itk > itk_unsigned_long
-      && (flags & CPP_N_WIDTH) != CPP_N_LARGE
-      && !in_system_header && !flag_isoc99)
-    pedwarn (input_location, 0, "integer constant is too large for %qs type",
-	     (flags & CPP_N_UNSIGNED) ? "unsigned long" : "long");
+    {
+      type = integer_types[itk];
+      if (itk > itk_unsigned_long
+	  && (flags & CPP_N_WIDTH) != CPP_N_LARGE)
+	emit_diagnostic 
+	  ((c_dialect_cxx () ? cxx_dialect == cxx98 : !flag_isoc99)
+	   ? DK_PEDWARN : DK_WARNING,
+	   input_location, OPT_Wlong_long,
+	   (flags & CPP_N_UNSIGNED) 
+	   ? "integer constant is too large for %<unsigned long%> type"
+	   : "integer constant is too large for %<long%> type");
+    }
 
   value = build_int_cst_wide (type, integer.low, integer.high);
 
   /* Convert imaginary to a complex type.  */
   if (flags & CPP_N_IMAGINARY)
Index: gcc/testsuite/gcc.dg/wtr-int-type-1.c
===================================================================
--- gcc/testsuite/gcc.dg/wtr-int-type-1.c	(revision 141265)
+++ gcc/testsuite/gcc.dg/wtr-int-type-1.c	(working copy)
@@ -23,13 +23,21 @@ testfunc ()
      we can pretend it worked the way it does in C99.]  */
   i = 9223372036854775807;
 
   /* But this one should, since it doesn't fit in long (long), but
      does fit in unsigned long (long).  */
-  i = 18446744073709551615; /* { dg-warning "decimal constant|unsigned" "decimal constant" } */
-  
+  i = 18446744073709551615; /* { dg-warning "integer constant is so large that it is unsigned" "decimal constant" } */
+  /* { dg-warning "this decimal constant would be unsigned in ISO C90" "decimal constant" { target *-*-* } 28 } */
+
 # 29 "sys-header.h" 3
+}
+
+void
+testfunc2( ) 
+{ 
+  long long i;
+
 /* We are in system headers now, no -Wtraditional warnings should issue.  */
 
   i = 0x80000000;
   i = 0xFFFFFFFF;
   i = 037777777777;
@@ -39,5 +47,6 @@ testfunc ()
   i = 01777777777777777777777;
   
   i = 9223372036854775807;
   i = 18446744073709551615;
 }
+
Index: gcc/testsuite/gcc.dg/c99-longlong-2.c
===================================================================
--- gcc/testsuite/gcc.dg/c99-longlong-2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/c99-longlong-2.c	(revision 0)
@@ -0,0 +1,6 @@
+/* Test for long long: if explicit Wlong-long, in C99 only warn, not
+   pedwarn.  */
+/* { dg-do compile } */
+/* { dg-options "-std=iso9899:1999 -pedantic-errors -Wlong-long" } */
+
+long long foo; /* { dg-warning "long long" } */
Index: gcc/testsuite/g++.dg/warn/pr13358-2.C
===================================================================
--- gcc/testsuite/g++.dg/warn/pr13358-2.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/pr13358-2.C	(revision 0)
@@ -0,0 +1,24 @@
+// PR c++/13358: g++ should accept a long long constant sans LL suffix
+// if -Wno-long-long is in use.
+// { dg-do compile }
+// { dg-require-effective-target int32plus }
+// { dg-options "-std=c++98 -pedantic-errors" }
+
+
+void use_longlong ()
+{
+  unsigned long long x1, x2, x3; // { dg-error "ISO C\\+\\+ 1998 does not support 'long long'" }
+  // make sure we error with hex, decimal and octal
+  x1 = 0x1b27da572ef3cd86; // { dg-error "integer constant is too large for 'long' type" "long long" { target ilp32 } }
+  x2 = 1956772631100509574; // { dg-error "integer constant is too large for 'long' type" "long long" { target ilp32 } }
+  x3 = 0154476645345674746606; // { dg-error "integer constant is too large for 'long' type" "long long" { target ilp32 } }
+}
+
+void use_longlong2 ()
+{
+  unsigned long long x1, x2, x3; // { dg-error "ISO C\\+\\+ 1998 does not support 'long long'" }
+  // make sure we error with hex, decimal and octal
+  x1 = 0x1b27da572ef3cd86LL; // { dg-error "long long" }
+  x2 = 1956772631100509574LL; // { dg-error "long long" }
+  x3 = 0154476645345674746606LL; // { dg-error "long long" }
+}
Index: gcc/testsuite/g++.dg/warn/pr13358-3.C
===================================================================
--- gcc/testsuite/g++.dg/warn/pr13358-3.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/pr13358-3.C	(revision 0)
@@ -0,0 +1,24 @@
+// PR c++/13358: g++ should accept a long long constant sans LL suffix
+// if -Wno-long-long is in use
+// { dg-do compile }
+// { dg-require-effective-target int32plus } 
+// { dg-options "-std=c++0x -pedantic-errors" }
+
+
+void use_longlong ()
+{
+  unsigned long long x1, x2, x3; 
+  // make sure it's ok with hex, decimal and octal
+  x1 = 0x1b27da572ef3cd86;
+  x2 = 1956772631100509574;
+  x3 = 0154476645345674746606;
+}
+
+void use_longlong2 ()
+{
+  unsigned long long x1, x2, x3; 
+  // make sure it's ok with hex, decimal and octal
+  x1 = 0x1b27da572ef3cd86LL;
+  x2 = 1956772631100509574LL;
+  x3 = 0154476645345674746606LL;
+}
Index: gcc/testsuite/g++.dg/warn/pr13358-4.C
===================================================================
--- gcc/testsuite/g++.dg/warn/pr13358-4.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/pr13358-4.C	(revision 0)
@@ -0,0 +1,24 @@
+// PR c++/13358: g++ should accept a long long constant sans LL suffix
+// if -Wno-long-long is in use.
+// { dg-do compile }
+// { dg-require-effective-target int32plus } 
+// { dg-options "-std=c++0x -pedantic-errors -Wlong-long" }
+
+
+void use_longlong ()
+{
+  unsigned long long x1, x2, x3; // { dg-warning "ISO C\\+\\+ 1998 does not support 'long long'" }
+  // make sure we warn with hex, decimal and octal
+  x1 = 0x1b27da572ef3cd86; // { dg-warning "integer constant is too large for 'long' type" "long long" { target ilp32 } }
+  x2 = 1956772631100509574; // { dg-warning "integer constant is too large for 'long' type" "long long" { target ilp32 } }
+  x3 = 0154476645345674746606; // { dg-warning "integer constant is too large for 'long' type" "long long" { target ilp32 } }
+}
+
+void use_longlong2 ()
+{
+  unsigned long long x1, x2, x3; // { dg-warning "ISO C\\+\\+ 1998 does not support 'long long'" }
+  // make sure we warn with hex, decimal and octal
+  x1 = 0x1b27da572ef3cd86LL; // { dg-warning "long long" }
+  x2 = 1956772631100509574LL; // { dg-warning "long long" }
+  x3 = 0154476645345674746606LL; // { dg-warning "long long" }
+}
Index: gcc/testsuite/g++.dg/warn/pr13358.C
===================================================================
--- gcc/testsuite/g++.dg/warn/pr13358.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/pr13358.C	(revision 0)
@@ -0,0 +1,24 @@
+// PR c++/13358: g++ should accept a long long constant sans LL suffix
+// if -Wno-long-long is in use.
+// { dg-do compile }
+// { dg-require-effective-target int32plus } 
+// { dg-options "-std=c++98 -Wno-long-long -pedantic-errors" }
+
+
+void use_longlong ()
+{
+  unsigned long long x1, x2, x3; 
+  // make sure it's ok with hex, decimal and octal
+  x1 = 0x1b27da572ef3cd86;
+  x2 = 1956772631100509574;
+  x3 = 0154476645345674746606;
+}
+
+void use_longlong2 ()
+{
+  unsigned long long x1, x2, x3; 
+  // make sure it's ok with hex, decimal and octal
+  x1 = 0x1b27da572ef3cd86LL;
+  x2 = 1956772631100509574LL;
+  x3 = 0154476645345674746606LL;
+}
Index: gcc/cp/error.c
===================================================================
--- gcc/cp/error.c	(revision 141265)
+++ gcc/cp/error.c	(working copy)
@@ -2704,5 +2704,24 @@ maybe_warn_cpp0x (const char* str)
 void
 maybe_warn_variadic_templates (void)
 {
   maybe_warn_cpp0x ("variadic templates");
 }
+
+
+/* Issue an ISO C++98 pedantic warning MSGID.  This function is supposed to
+   be used for matters that are allowed in ISO C++0x but not supported in
+   ISO C++98, thus we explicitly don't pedwarn when ISO c++0x is specified.  */
+
+bool
+pedwarn_cxx98 (location_t location, int opt, const char *gmsgid, ...)
+{
+  diagnostic_info diagnostic;
+  va_list ap;
+
+  va_start (ap, gmsgid);
+  diagnostic_set_info (&diagnostic, gmsgid, &ap, location,
+		       (cxx_dialect == cxx98) ? DK_PEDWARN : DK_WARNING);
+  diagnostic.option_index = opt;
+  va_end (ap);
+  return report_diagnostic (&diagnostic);
+}
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h	(revision 141265)
+++ gcc/cp/cp-tree.h	(working copy)
@@ -4432,10 +4432,11 @@ extern const char *lang_decl_name		(tree
 extern const char *language_to_string		(enum languages);
 extern const char *class_key_or_enum_as_string	(tree);
 extern void print_instantiation_context		(void);
 extern void maybe_warn_variadic_templates       (void);
 extern void maybe_warn_cpp0x			(const char *);
+extern bool pedwarn_cxx98                       (location_t, int, const char *, ...) ATTRIBUTE_GCC_CXXDIAG(3,4);
 
 /* in except.c */
 extern void init_exception_processing		(void);
 extern tree expand_start_catch_block		(tree);
 extern void expand_end_catch_block		(void);
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 141265)
+++ gcc/cp/parser.c	(working copy)
@@ -2162,14 +2162,13 @@ cp_parser_check_decl_spec (cp_decl_speci
       /* The "long" specifier is a special case because of "long long".  */
       if (ds == ds_long)
 	{
 	  if (count > 2)
 	    error ("%H%<long long long%> is too long for GCC", &location);
-	  else if (pedantic && !in_system_header && warn_long_long
-                   && cxx_dialect == cxx98)
-	    pedwarn (location, OPT_Wlong_long, 
-		     "ISO C++ 1998 does not support %<long long%>");
+	  else 
+	    pedwarn_cxx98 (location, OPT_Wlong_long, 
+			   "ISO C++ 1998 does not support %<long long%>");
 	}
       else if (count > 1)
 	{
 	  static const char *const decl_spec_names[] = {
 	    "signed",
Index: gcc/c-decl.c
===================================================================
--- gcc/c-decl.c	(revision 141265)
+++ gcc/c-decl.c	(working copy)
@@ -7214,12 +7214,12 @@ declspecs_add_type (struct c_declspecs *
 		    {
 		      error ("both %<long long%> and %<double%> in "
 			     "declaration specifiers");
 		      break;
 		    }
-		  if (pedantic && !flag_isoc99 && !in_system_header)
-		    pedwarn (input_location, OPT_Wlong_long, "ISO C90 does not support %<long long%>");
+		  pedwarn_c90 (input_location, OPT_Wlong_long, 
+			       "ISO C90 does not support %<long long%>");
 		  specs->long_long_p = 1;
 		  break;
 		}
 	      if (specs->short_p)
 		error ("both %<long%> and %<short%> in "
Index: gcc/c.opt
===================================================================
--- gcc/c.opt	(revision 141265)
+++ gcc/c.opt	(working copy)
@@ -279,11 +279,11 @@ Warn about invalid uses of the \"offseto
 Winvalid-pch
 C ObjC C++ ObjC++ Warning
 Warn about PCH files that are found but not used
 
 Wlong-long
-C ObjC C++ ObjC++ Var(warn_long_long) Init(1) Warning
+C ObjC C++ ObjC++ Var(warn_long_long) Init(-1) Warning
 Do not warn about using \"long long\" when -pedantic
 
 Wmain
 C ObjC C++ ObjC++ Var(warn_main) Init(-1) Warning
 Warn about suspicious declarations of \"main\"
Index: gcc/c-opts.c
===================================================================
--- gcc/c-opts.c	(revision 141265)
+++ gcc/c-opts.c	(working copy)
@@ -1394,18 +1394,19 @@ sanitize_cpp_opts (void)
     error ("-MG may only be used with -M or -MM");
 
   cpp_opts->unsigned_char = !flag_signed_char;
   cpp_opts->stdc_0_in_system_headers = STDC_0_IN_SYSTEM_HEADERS;
 
-  /* We want -Wno-long-long to override -pedantic -std=non-c99
-     and/or -Wtraditional, whatever the ordering.  */
-  cpp_opts->warn_long_long
-    = warn_long_long && ((pedantic
-			  && (c_dialect_cxx ()
-			      ? cxx_dialect == cxx98
-			      : !flag_isoc99))
-                         || warn_traditional);
+  /* Wlong-long is disabled by default. It is enabled by:
+      [-pedantic | -Wtraditional] -std=[gnu|c]++98 ; or
+      [-pedantic | -Wtraditional] -std=non-c99 . 
+
+      Either -Wlong-long or -Wno-long-long override any other settings.  */
+  if (warn_long_long == -1)
+    warn_long_long = ((pedantic || warn_traditional)
+		      && (c_dialect_cxx () ? cxx_dialect == cxx98 : !flag_isoc99));
+  cpp_opts->warn_long_long = warn_long_long;
 
   /* Similarly with -Wno-variadic-macros.  No check for c99 here, since
      this also turns off warnings about GCCs extension.  */
   cpp_opts->warn_variadic_macros
     = warn_variadic_macros && (pedantic || warn_traditional);
Index: gcc/c-parser.c
===================================================================
--- gcc/c-parser.c	(revision 141265)
+++ gcc/c-parser.c	(working copy)
@@ -815,18 +815,16 @@ disable_extension_diagnostics (void)
 {
   int ret = (pedantic
 	     | (warn_pointer_arith << 1)
 	     | (warn_traditional << 2)
 	     | (flag_iso << 3)
-	     | (warn_long_long << 4)
-	     | (cpp_opts->warn_long_long << 5));
+	     | (warn_long_long << 4));
   cpp_opts->pedantic = pedantic = 0;
   warn_pointer_arith = 0;
   cpp_opts->warn_traditional = warn_traditional = 0;
   flag_iso = 0;
-  warn_long_long = 0;
-  cpp_opts->warn_long_long = 0;
+  cpp_opts->warn_long_long = warn_long_long = 0;
   return ret;
 }
 
 /* Restore the warning flags which are controlled by __extension__.
    FLAGS is the return value from disable_extension_diagnostics.  */
@@ -836,12 +834,11 @@ restore_extension_diagnostics (int flags
 {
   cpp_opts->pedantic = pedantic = flags & 1;
   warn_pointer_arith = (flags >> 1) & 1;
   cpp_opts->warn_traditional = warn_traditional = (flags >> 2) & 1;
   flag_iso = (flags >> 3) & 1;
-  warn_long_long = (flags >> 4) & 1;
-  cpp_opts->warn_long_long = (flags >> 5) & 1;
+  cpp_opts->warn_long_long = warn_long_long = (flags >> 4) & 1;
 }
 
 /* Possibly kinds of declarator to parse.  */
 typedef enum c_dtr_syn {
   /* A normal declarator with an identifier.  */
Index: libcpp/init.c
===================================================================
--- libcpp/init.c	(revision 141265)
+++ libcpp/init.c	(working copy)
@@ -157,11 +157,11 @@ cpp_create_reader (enum c_lang lang, has
   CPP_OPTION (pfile, tabstop) = 8;
   CPP_OPTION (pfile, operator_names) = 1;
   CPP_OPTION (pfile, warn_trigraphs) = 2;
   CPP_OPTION (pfile, warn_endif_labels) = 1;
   CPP_OPTION (pfile, warn_deprecated) = 1;
-  CPP_OPTION (pfile, warn_long_long) = !CPP_OPTION (pfile, c99);
+  CPP_OPTION (pfile, warn_long_long) = 0;
   CPP_OPTION (pfile, dollars_in_ident) = 1;
   CPP_OPTION (pfile, warn_dollars) = 1;
   CPP_OPTION (pfile, warn_variadic_macros) = 1;
   CPP_OPTION (pfile, warn_builtin_macro_redefined) = 1;
   CPP_OPTION (pfile, warn_normalize) = normalized_C;
Index: libcpp/expr.c
===================================================================
--- libcpp/expr.c	(revision 141265)
+++ libcpp/expr.c	(working copy)
@@ -393,14 +393,16 @@ cpp_classify_number (cpp_reader *pfile, 
 		       "traditional C rejects the \"%.*s\" suffix",
 		       (int) (limit - str), str);
 	}
 
       if ((result & CPP_N_WIDTH) == CPP_N_LARGE
-	  && ! CPP_OPTION (pfile, c99)
 	  && CPP_OPTION (pfile, warn_long_long))
-	cpp_error (pfile, CPP_DL_PEDWARN,
-		   "use of C99 long long integer constant");
+	cpp_error (pfile, 
+		   CPP_OPTION (pfile, c99) ? CPP_DL_WARNING : CPP_DL_PEDWARN,
+		   CPP_OPTION (pfile, cplusplus) 
+		   ? "use of C++0x long long integer constant"
+		   : "use of C99 long long integer constant");
 
       result |= CPP_N_INTEGER;
     }
 
  syntax_ok:

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]