r238129 - Bug fix for PR23577 (https://llvm.org/bugs/show_bug.cgi?id=23577#c0).

Alexander Musman alexander.musman at gmail.com
Mon May 25 04:21:22 PDT 2015


Author: amusman
Date: Mon May 25 06:21:20 2015
New Revision: 238129

URL: http://llvm.org/viewvc/llvm-project?rev=238129&view=rev
Log:
Bug fix for PR23577 (https://llvm.org/bugs/show_bug.cgi?id=23577#c0).
"1-4" specifiers are returned as numeric constants, not identifiers,
and should be treated as such. Currently pragma handler incorrectly
assumes that they are returned as identifiers.

Patch by Andrey Bokhanko.

Differential Revision: http://reviews.llvm.org/D9856


Modified:
    cfe/trunk/lib/Lex/Pragma.cpp
    cfe/trunk/test/Preprocessor/pragma_microsoft.c

Modified: cfe/trunk/lib/Lex/Pragma.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/Pragma.cpp?rev=238129&r1=238128&r2=238129&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/Pragma.cpp (original)
+++ cfe/trunk/lib/Lex/Pragma.cpp Mon May 25 06:21:20 2015
@@ -22,6 +22,7 @@
 #include "clang/Lex/Preprocessor.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/CrashRecoveryContext.h"
 #include "llvm/Support/ErrorHandling.h"
 #include <algorithm>
@@ -1036,12 +1037,8 @@ struct PragmaWarningHandler : public Pra
 
     PP.Lex(Tok);
     IdentifierInfo *II = Tok.getIdentifierInfo();
-    if (!II) {
-      PP.Diag(Tok, diag::warn_pragma_warning_spec_invalid);
-      return;
-    }
 
-    if (II->isStr("push")) {
+    if (II && II->isStr("push")) {
       // #pragma warning( push[ ,n ] )
       int Level = -1;
       PP.Lex(Tok);
@@ -1058,7 +1055,7 @@ struct PragmaWarningHandler : public Pra
       }
       if (Callbacks)
         Callbacks->PragmaWarningPush(DiagLoc, Level);
-    } else if (II->isStr("pop")) {
+    } else if (II && II->isStr("pop")) {
       // #pragma warning( pop )
       PP.Lex(Tok);
       if (Callbacks)
@@ -1068,23 +1065,40 @@ struct PragmaWarningHandler : public Pra
       //                  [; warning-specifier : warning-number-list...] )
       while (true) {
         II = Tok.getIdentifierInfo();
-        if (!II) {
+        if (!II && !Tok.is(tok::numeric_constant)) {
           PP.Diag(Tok, diag::warn_pragma_warning_spec_invalid);
           return;
         }
 
         // Figure out which warning specifier this is.
-        StringRef Specifier = II->getName();
-        bool SpecifierValid =
-            llvm::StringSwitch<bool>(Specifier)
-                .Cases("1", "2", "3", "4", true)
-                .Cases("default", "disable", "error", "once", "suppress", true)
-                .Default(false);
+        bool SpecifierValid;
+        StringRef Specifier;
+        llvm::SmallString<1> SpecifierBuf;
+        if (II) {
+          Specifier = II->getName();
+          SpecifierValid = llvm::StringSwitch<bool>(Specifier)
+                               .Cases("default", "disable", "error", "once",
+                                      "suppress", true)
+                               .Default(false);
+          // If we read a correct specifier, snatch next token (that should be
+          // ":", checked later).
+          if (SpecifierValid)
+            PP.Lex(Tok);
+        } else {
+          // Token is a numeric constant. It should be either 1, 2, 3 or 4.
+          uint64_t Value;
+          Specifier = PP.getSpelling(Tok, SpecifierBuf);
+          if (PP.parseSimpleIntegerLiteral(Tok, Value)) {
+            SpecifierValid = (Value >= 1) && (Value <= 4);
+          } else
+            SpecifierValid = false;
+          // Next token already snatched by parseSimpleIntegerLiteral.
+        }
+
         if (!SpecifierValid) {
           PP.Diag(Tok, diag::warn_pragma_warning_spec_invalid);
           return;
         }
-        PP.Lex(Tok);
         if (Tok.isNot(tok::colon)) {
           PP.Diag(Tok, diag::warn_pragma_warning_expected) << ":";
           return;

Modified: cfe/trunk/test/Preprocessor/pragma_microsoft.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Preprocessor/pragma_microsoft.c?rev=238129&r1=238128&r2=238129&view=diff
==============================================================================
--- cfe/trunk/test/Preprocessor/pragma_microsoft.c (original)
+++ cfe/trunk/test/Preprocessor/pragma_microsoft.c Mon May 25 06:21:20 2015
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 %s -fsyntax-only -verify -fms-extensions
+// RUN: not %clang_cc1 %s -fms-extensions -E | FileCheck %s
 // REQUIRES: non-ps4-sdk
 
 // rdar://6495941
@@ -7,27 +8,41 @@
 #define BAR "2"
 
 #pragma comment(linker,"foo=" FOO) // expected-error {{pragma comment requires parenthesized identifier and optional string}}
+// CHECK: #pragma comment(linker,"foo=" 1)
 #pragma comment(linker," bar=" BAR)
+// CHECK: #pragma comment(linker," bar=" "2")
 
 #pragma comment( user, "Compiled on " __DATE__ " at " __TIME__ ) 
+// CHECK: {{#pragma comment\( user, \"Compiled on \".*\" at \".*\" \)}}
 
 #pragma comment(foo)    // expected-error {{unknown kind of pragma comment}}
+// CHECK: #pragma comment(foo)
 #pragma comment(compiler,)     // expected-error {{expected string literal in pragma comment}}
+// CHECK: #pragma comment(compiler,)
 #define foo compiler
 #pragma comment(foo)   // macro expand kind.
+// CHECK: #pragma comment(compiler)
 #pragma comment(foo) x // expected-error {{pragma comment requires}}
+// CHECK: #pragma comment(compiler) x
 
 #pragma comment(user, "foo\abar\nbaz\tsome	thing")
+// CHECK: #pragma comment(user, "foo\abar\nbaz\tsome	thing")
 
 #pragma detect_mismatch("test", "1")
+// CHECK: #pragma detect_mismatch("test", "1")
 #pragma detect_mismatch()  // expected-error {{expected string literal in pragma detect_mismatch}}
+// CHECK: #pragma detect_mismatch()
 #pragma detect_mismatch("test") // expected-error {{pragma detect_mismatch is malformed; it requires two comma-separated string literals}}
+// CHECK: #pragma detect_mismatch("test")
 #pragma detect_mismatch("test", 1) // expected-error {{expected string literal in pragma detect_mismatch}}
+// CHECK: #pragma detect_mismatch("test", 1)
 #pragma detect_mismatch("test", BAR)
+// CHECK: #pragma detect_mismatch("test", "2")
 
 // __pragma
 
-__pragma(comment(linker," bar=" BAR))                                            
+__pragma(comment(linker," bar=" BAR))
+// CHECK: #pragma comment(linker," bar=" "2")
 
 #define MACRO_WITH__PRAGMA { \
   __pragma(warning(push)); \
@@ -39,11 +54,16 @@ __pragma(comment(linker," bar=" BAR))
 void f()
 {
   __pragma()
+// CHECK: #pragma
 
   // If we ever actually *support* __pragma(warning(disable: x)),
   // this warning should go away.
   MACRO_WITH__PRAGMA // expected-warning {{lower precedence}} \
                      // expected-note 2 {{place parentheses}}
+// CHECK: #pragma warning(push)
+// CHECK: #pragma warning(disable: 10000)
+// CHECK: ; 1 + (2 > 3) ? 4 : 5;
+// CHECK: #pragma warning(pop)
 }
 
 
@@ -91,26 +111,49 @@ void g() {}
 
 // Test that we ignore pragma warning.
 #pragma warning(push)
+// CHECK: #pragma warning(push)
 #pragma warning(push, 1)
+// CHECK: #pragma warning(push, 1)
 #pragma warning(disable : 4705)
+// CHECK: #pragma warning(disable: 4705)
 #pragma warning(disable : 123 456 789 ; error : 321)
+// CHECK: #pragma warning(disable: 123 456 789)
+// CHECK: #pragma warning(error: 321)
 #pragma warning(once : 321)
+// CHECK: #pragma warning(once: 321)
 #pragma warning(suppress : 321)
+// CHECK: #pragma warning(suppress: 321)
 #pragma warning(default : 321)
+// CHECK: #pragma warning(default: 321)
 #pragma warning(pop)
+// CHECK: #pragma warning(pop)
+#pragma warning(1: 123)
+// CHECK: #pragma warning(1: 123)
+#pragma warning(2: 234 567)
+// CHECK: #pragma warning(2: 234 567)
+#pragma warning(3: 123; 4: 678)
+// CHECK: #pragma warning(3: 123)
+// CHECK: #pragma warning(4: 678)
+#pragma warning(5: 123) // expected-warning {{expected 'push', 'pop', 'default', 'disable', 'error', 'once', 'suppress', 1, 2, 3, or 4}}
 
 #pragma warning(push, 0)
+// CHECK: #pragma warning(push, 0)
 // FIXME: We could probably support pushing warning level 0.
 #pragma warning(pop)
+// CHECK: #pragma warning(pop)
 
 #pragma warning  // expected-warning {{expected '('}}
 #pragma warning(   // expected-warning {{expected 'push', 'pop', 'default', 'disable', 'error', 'once', 'suppress', 1, 2, 3, or 4}}
 #pragma warning()   // expected-warning {{expected 'push', 'pop', 'default', 'disable', 'error', 'once', 'suppress', 1, 2, 3, or 4}}
 #pragma warning(push 4)  // expected-warning {{expected ')'}}
+// CHECK: #pragma warning(push)
 #pragma warning(push  // expected-warning {{expected ')'}}
+// CHECK: #pragma warning(push)
 #pragma warning(push, 5)  // expected-warning {{requires a level between 0 and 4}}
 #pragma warning(pop, 1)  // expected-warning {{expected ')'}}
+// CHECK: #pragma warning(pop)
 #pragma warning(push, 1) asdf // expected-warning {{extra tokens at end of #pragma warning directive}}
+// CHECK: #pragma warning(push, 1)
 #pragma warning(disable 4705) // expected-warning {{expected ':'}}
 #pragma warning(disable : 0) // expected-warning {{expected a warning number}}
 #pragma warning(default 321) // expected-warning {{expected ':'}}





More information about the cfe-commits mailing list