Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
"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

llvm-svn: 238129
  • Loading branch information
amusman committed May 25, 2015
1 parent 654e0ca commit 6b080fc
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 15 deletions.
42 changes: 28 additions & 14 deletions clang/lib/Lex/Pragma.cpp
Expand Up @@ -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>
Expand Down Expand Up @@ -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);
Expand All @@ -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)
Expand All @@ -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;
Expand Down
45 changes: 44 additions & 1 deletion clang/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
Expand All @@ -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)); \
Expand All @@ -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)
}


Expand Down Expand Up @@ -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 ':'}}
Expand Down

0 comments on commit 6b080fc

Please sign in to comment.