diff options
author | Alexander Musman <alexander.musman@gmail.com> | 2015-05-25 11:21:20 +0000 |
---|---|---|
committer | Alexander Musman <alexander.musman@gmail.com> | 2015-05-25 11:21:20 +0000 |
commit | 0495e8d5caf982bc13d8c2ac6a9a221480750119 (patch) | |
tree | f18541df5078ce5d4fb3409ca3fa2dc201439151 | |
parent | 9a5a6f0e149ba035168641ca6dc4e3b3e5aa29b5 (diff) | |
download | clang-0495e8d5caf982bc13d8c2ac6a9a221480750119.tar.gz |
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
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@238129 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Lex/Pragma.cpp | 42 | ||||
-rw-r--r-- | test/Preprocessor/pragma_microsoft.c | 45 |
2 files changed, 72 insertions, 15 deletions
diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp index 6facf4c80b..26ed674f65 100644 --- a/lib/Lex/Pragma.cpp +++ b/lib/Lex/Pragma.cpp @@ -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 PragmaHandler { 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 PragmaHandler { } 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 PragmaHandler { // [; 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; diff --git a/test/Preprocessor/pragma_microsoft.c b/test/Preprocessor/pragma_microsoft.c index 6b88dece98..b6921fa42f 100644 --- a/test/Preprocessor/pragma_microsoft.c +++ b/test/Preprocessor/pragma_microsoft.c @@ -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 ':'}} |