]> granicus.if.org Git - clang/commitdiff
Implement -Wfour-char-constants, which is an extension, not an extwarn,
authorChris Lattner <sabre@nondot.org>
Tue, 28 Apr 2009 21:51:46 +0000 (21:51 +0000)
committerChris Lattner <sabre@nondot.org>
Tue, 28 Apr 2009 21:51:46 +0000 (21:51 +0000)
and apparently not part of -Wall

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70329 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticGroups.td
include/clang/Basic/DiagnosticLexKinds.td
lib/Lex/LiteralSupport.cpp
test/Lexer/constants.c

index c0afde52d3cb79fbb4c0a7d2c9abd32dbdc13305..18ca0c380ed2fce1bb4efb057cf6ec7cd6cdf32e 100644 (file)
@@ -33,7 +33,7 @@ def : DiagGroup<"declaration-after-statement">;
 def : DiagGroup<"format-security">;
 def : DiagGroup<"format=2">;
 def : DiagGroup<"format">;
-def : DiagGroup<"four-char-constants">;
+def FourByteMultiChar : DiagGroup<"four-char-constants">;
 
 
 def : DiagGroup<"init-self">;
index 471b13687323171ee3e7b3394311a643543298fb..893878714bae5e19de54e9b2be81988e9df70cbe 100644 (file)
@@ -53,6 +53,9 @@ def err_invalid_character_to_charify : Error<
   "invalid argument to convert to character">;
 def ext_multichar_character_literal : ExtWarn<
   "multi-character character constant">, InGroup<MultiChar>;
+def ext_four_char_character_literal : Extension<
+  "multi-character character constant">, InGroup<FourByteMultiChar>;
+  
 
 // Literal
 def ext_nonstandard_escape : Extension<
index faa44b6fb0609927ec452a5d825202d14caa174e..398082ff70c4301d82aafe66b36d1493b7429d07 100644 (file)
@@ -631,19 +631,19 @@ CharLiteralParser::CharLiteralParser(const char *begin, const char *end,
 
   // FIXME: The "Value" is an uint64_t so we can handle char literals of 
   // upto 64-bits.
-  assert(PP.getTargetInfo().getIntWidth() <= 64 &&
-         "Assumes sizeof(int) on target is <= 64");
-  assert(PP.getTargetInfo().getWCharWidth() <= 64 &&
-         "Assumes sizeof(wchar) on target is <= 64");
   // FIXME: This extensively assumes that 'char' is 8-bits.
   assert(PP.getTargetInfo().getCharWidth() == 8 &&
          "Assumes char is 8 bits");
+  assert(PP.getTargetInfo().getIntWidth() <= 64 &&
+         (PP.getTargetInfo().getIntWidth() & 7) == 0 &&
+         "Assumes sizeof(int) on target is <= 64 and a multiple of char");
+  assert(PP.getTargetInfo().getWCharWidth() <= 64 &&
+         "Assumes sizeof(wchar) on target is <= 64");
 
   // This is what we will use for overflow detection 
   llvm::APInt LitVal(PP.getTargetInfo().getIntWidth(), 0);
   
-  bool isFirstChar = true;
-  bool isMultiChar = false;
+  unsigned NumCharsSoFar = 0;
   while (begin[0] != '\'') {
     uint64_t ResultChar;
     if (begin[0] != '\\')     // If this is a normal character, consume it.
@@ -653,33 +653,33 @@ CharLiteralParser::CharLiteralParser(const char *begin, const char *end,
 
     // If this is a multi-character constant (e.g. 'abc'), handle it.  These are
     // implementation defined (C99 6.4.4.4p10).
-    if (!isFirstChar) {
-      // If this is the second character being processed, do special handling.
-      if (!isMultiChar) {
-        isMultiChar = true;
-      
-        // Warn about discarding the top bits for multi-char wide-character
-        // constants (L'abcd').
-        if (IsWide)
-          PP.Diag(Loc, diag::warn_extraneous_wide_char_constant);
-        else
-          PP.Diag(Loc, diag::ext_multichar_character_literal);
-      }
-
+    if (NumCharsSoFar) {
       if (IsWide) {
         // Emulate GCC's (unintentional?) behavior: L'ab' -> L'b'.
         LitVal = 0;
       } else {
         // Narrow character literals act as though their value is concatenated
-        // in this implementation.
-        if ((LitVal.shl(8)).lshr(8) != LitVal)
+        // in this implementation, but warn on overflow.
+        if (LitVal.countLeadingZeros() < 8)
           PP.Diag(Loc, diag::warn_char_constant_too_large);
         LitVal <<= 8;
       }
     }
     
     LitVal = LitVal + ResultChar;
-    isFirstChar = false;
+    ++NumCharsSoFar;
+  }
+
+  // If this is the second character being processed, do special handling.
+  if (NumCharsSoFar > 1) {
+    // Warn about discarding the top bits for multi-char wide-character
+    // constants (L'abcd').
+    if (IsWide)
+      PP.Diag(Loc, diag::warn_extraneous_wide_char_constant);
+    else if (NumCharsSoFar != 4)
+      PP.Diag(Loc, diag::ext_multichar_character_literal);
+    else
+      PP.Diag(Loc, diag::ext_four_char_character_literal);
   }
 
   // Transfer the value from APInt to uint64_t
@@ -689,7 +689,7 @@ CharLiteralParser::CharLiteralParser(const char *begin, const char *end,
   // if 'char' is signed for this target (C99 6.4.4.4p10).  Note that multiple
   // character constants are not sign extended in the this implementation:
   // '\xFF\xFF' = 65536 and '\x0\xFF' = 255, which matches GCC.
-  if (!IsWide && !isMultiChar && (Value & 128) &&
+  if (!IsWide && NumCharsSoFar == 1 && (Value & 128) &&
       PP.getTargetInfo().isCharSigned())
     Value = (signed char)Value;
 }
index f5fc9e1493e64c4ce0663f5a8a70bb4b7e63446c..c0355314b2640126fc325d55abe588a6055e39e5 100644 (file)
@@ -16,14 +16,20 @@ float Y = 08.123456;
 
 
 char c[] = {
-  'df',  // expected-warning {{multi-character character constant}}
+  'df',   // expected-warning {{multi-character character constant}}
   '\t',
   '\\
 t',
-  '??!'  // expected-warning {{trigraph converted to '|' character}}
+  '??!',  // expected-warning {{trigraph converted to '|' character}}
+  'abcd'  // expected-warning {{multi-character character constant}}
 };
 
 
 #pragma GCC diagnostic ignored "-Wmultichar"
 
 char d = 'df'; // no warning.
+char e = 'abcd';  // still warn: expected-warning {{multi-character character constant}}
+
+#pragma GCC diagnostic ignored "-Wfour-char-constants"
+
+char f = 'abcd';  // ignored.