mirror of https://github.com/microsoft/clang.git
Fix parsing certain kinds of strings in the MS section pragmas
We were crashing on the relevant test case inputs. Also, refactor this code a bit so we can report failure and slurp the pragma tokens without returning a diagnostic id. This is more consistent with the rest of the parser and sema code. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@213337 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
874648372c
commit
fadb218b32
|
@ -811,6 +811,8 @@ def warn_pragma_extra_tokens_at_eol : Warning<
|
||||||
InGroup<IgnoredPragmas>;
|
InGroup<IgnoredPragmas>;
|
||||||
def warn_pragma_expected_punc : Warning<
|
def warn_pragma_expected_punc : Warning<
|
||||||
"expected ')' or ',' in '#pragma %0'">, InGroup<IgnoredPragmas>;
|
"expected ')' or ',' in '#pragma %0'">, InGroup<IgnoredPragmas>;
|
||||||
|
def warn_pragma_expected_non_wide_string : Warning<
|
||||||
|
"expected non-wide string literal in '#pragma %0'">, InGroup<IgnoredPragmas>;
|
||||||
// - #pragma options
|
// - #pragma options
|
||||||
def warn_pragma_options_expected_align : Warning<
|
def warn_pragma_options_expected_align : Warning<
|
||||||
"expected 'align' following '#pragma options' - ignored">,
|
"expected 'align' following '#pragma options' - ignored">,
|
||||||
|
|
|
@ -486,12 +486,12 @@ private:
|
||||||
void HandlePragmaMSVtorDisp();
|
void HandlePragmaMSVtorDisp();
|
||||||
|
|
||||||
void HandlePragmaMSPragma();
|
void HandlePragmaMSPragma();
|
||||||
unsigned HandlePragmaMSSection(llvm::StringRef PragmaName,
|
bool HandlePragmaMSSection(StringRef PragmaName,
|
||||||
SourceLocation PragmaLocation);
|
SourceLocation PragmaLocation);
|
||||||
unsigned HandlePragmaMSSegment(llvm::StringRef PragmaName,
|
bool HandlePragmaMSSegment(StringRef PragmaName,
|
||||||
SourceLocation PragmaLocation);
|
SourceLocation PragmaLocation);
|
||||||
unsigned HandlePragmaMSInitSeg(llvm::StringRef PragmaName,
|
bool HandlePragmaMSInitSeg(StringRef PragmaName,
|
||||||
SourceLocation PragmaLocation);
|
SourceLocation PragmaLocation);
|
||||||
|
|
||||||
/// \brief Handle the annotation token produced for
|
/// \brief Handle the annotation token produced for
|
||||||
/// #pragma align...
|
/// #pragma align...
|
||||||
|
|
|
@ -467,11 +467,12 @@ void Parser::HandlePragmaMSPragma() {
|
||||||
PP.EnterTokenStream(TheTokens->first, TheTokens->second, true, true);
|
PP.EnterTokenStream(TheTokens->first, TheTokens->second, true, true);
|
||||||
SourceLocation PragmaLocation = ConsumeToken(); // The annotation token.
|
SourceLocation PragmaLocation = ConsumeToken(); // The annotation token.
|
||||||
assert(Tok.isAnyIdentifier());
|
assert(Tok.isAnyIdentifier());
|
||||||
llvm::StringRef PragmaName = Tok.getIdentifierInfo()->getName();
|
StringRef PragmaName = Tok.getIdentifierInfo()->getName();
|
||||||
PP.Lex(Tok); // pragma kind
|
PP.Lex(Tok); // pragma kind
|
||||||
|
|
||||||
// Figure out which #pragma we're dealing with. The switch has no default
|
// Figure out which #pragma we're dealing with. The switch has no default
|
||||||
// because lex shouldn't emit the annotation token for unrecognized pragmas.
|
// because lex shouldn't emit the annotation token for unrecognized pragmas.
|
||||||
typedef unsigned (Parser::*PragmaHandler)(llvm::StringRef, SourceLocation);
|
typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
|
||||||
PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName)
|
PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName)
|
||||||
.Case("data_seg", &Parser::HandlePragmaMSSegment)
|
.Case("data_seg", &Parser::HandlePragmaMSSegment)
|
||||||
.Case("bss_seg", &Parser::HandlePragmaMSSegment)
|
.Case("bss_seg", &Parser::HandlePragmaMSSegment)
|
||||||
|
@ -479,29 +480,46 @@ void Parser::HandlePragmaMSPragma() {
|
||||||
.Case("code_seg", &Parser::HandlePragmaMSSegment)
|
.Case("code_seg", &Parser::HandlePragmaMSSegment)
|
||||||
.Case("section", &Parser::HandlePragmaMSSection)
|
.Case("section", &Parser::HandlePragmaMSSection)
|
||||||
.Case("init_seg", &Parser::HandlePragmaMSInitSeg);
|
.Case("init_seg", &Parser::HandlePragmaMSInitSeg);
|
||||||
if (auto DiagID = (this->*Handler)(PragmaName, PragmaLocation)) {
|
|
||||||
PP.Diag(PragmaLocation, DiagID) << PragmaName;
|
if (!(this->*Handler)(PragmaName, PragmaLocation)) {
|
||||||
|
// Pragma handling failed, and has been diagnosed. Slurp up the tokens
|
||||||
|
// until eof (really end of line) to prevent follow-on errors.
|
||||||
while (Tok.isNot(tok::eof))
|
while (Tok.isNot(tok::eof))
|
||||||
PP.Lex(Tok);
|
PP.Lex(Tok);
|
||||||
PP.Lex(Tok);
|
PP.Lex(Tok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned Parser::HandlePragmaMSSection(llvm::StringRef PragmaName,
|
bool Parser::HandlePragmaMSSection(StringRef PragmaName,
|
||||||
SourceLocation PragmaLocation) {
|
SourceLocation PragmaLocation) {
|
||||||
if (Tok.isNot(tok::l_paren))
|
if (Tok.isNot(tok::l_paren)) {
|
||||||
return diag::warn_pragma_expected_lparen;
|
PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
PP.Lex(Tok); // (
|
PP.Lex(Tok); // (
|
||||||
// Parsing code for pragma section
|
// Parsing code for pragma section
|
||||||
if (Tok.isNot(tok::string_literal))
|
if (Tok.isNot(tok::string_literal)) {
|
||||||
return diag::warn_pragma_expected_section_name;
|
PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
|
||||||
StringLiteral *SegmentName =
|
<< PragmaName;
|
||||||
cast<StringLiteral>(ParseStringLiteralExpression().get());
|
return false;
|
||||||
|
}
|
||||||
|
ExprResult StringResult = ParseStringLiteralExpression();
|
||||||
|
if (StringResult.isInvalid())
|
||||||
|
return false; // Already diagnosed.
|
||||||
|
StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
|
||||||
|
if (SegmentName->getCharByteWidth() != 1) {
|
||||||
|
PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
|
||||||
|
<< PragmaName;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
int SectionFlags = 0;
|
int SectionFlags = 0;
|
||||||
while (Tok.is(tok::comma)) {
|
while (Tok.is(tok::comma)) {
|
||||||
PP.Lex(Tok); // ,
|
PP.Lex(Tok); // ,
|
||||||
if (!Tok.isAnyIdentifier())
|
if (!Tok.isAnyIdentifier()) {
|
||||||
return diag::warn_pragma_expected_action_or_r_paren;
|
PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
|
||||||
|
<< PragmaName;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
Sema::PragmaSectionFlag Flag =
|
Sema::PragmaSectionFlag Flag =
|
||||||
llvm::StringSwitch<Sema::PragmaSectionFlag>(
|
llvm::StringSwitch<Sema::PragmaSectionFlag>(
|
||||||
Tok.getIdentifierInfo()->getName())
|
Tok.getIdentifierInfo()->getName())
|
||||||
|
@ -515,43 +533,51 @@ unsigned Parser::HandlePragmaMSSection(llvm::StringRef PragmaName,
|
||||||
.Case("remove", Sema::PSF_Invalid)
|
.Case("remove", Sema::PSF_Invalid)
|
||||||
.Default(Sema::PSF_None);
|
.Default(Sema::PSF_None);
|
||||||
if (Flag == Sema::PSF_None || Flag == Sema::PSF_Invalid) {
|
if (Flag == Sema::PSF_None || Flag == Sema::PSF_Invalid) {
|
||||||
PP.Diag(PragmaLocation, Flag == Sema::PSF_None ?
|
PP.Diag(PragmaLocation, Flag == Sema::PSF_None
|
||||||
diag::warn_pragma_invalid_specific_action :
|
? diag::warn_pragma_invalid_specific_action
|
||||||
diag::warn_pragma_unsupported_action)
|
: diag::warn_pragma_unsupported_action)
|
||||||
<< PragmaName << Tok.getIdentifierInfo()->getName();
|
<< PragmaName << Tok.getIdentifierInfo()->getName();
|
||||||
while (Tok.isNot(tok::eof))
|
return false;
|
||||||
PP.Lex(Tok);
|
|
||||||
PP.Lex(Tok);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
SectionFlags |= Flag;
|
SectionFlags |= Flag;
|
||||||
PP.Lex(Tok); // Identifier
|
PP.Lex(Tok); // Identifier
|
||||||
}
|
}
|
||||||
if (Tok.isNot(tok::r_paren))
|
if (Tok.isNot(tok::r_paren)) {
|
||||||
return diag::warn_pragma_expected_rparen;
|
PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
PP.Lex(Tok); // )
|
PP.Lex(Tok); // )
|
||||||
if (Tok.isNot(tok::eof))
|
if (Tok.isNot(tok::eof)) {
|
||||||
return diag::warn_pragma_extra_tokens_at_eol;
|
PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
|
||||||
|
<< PragmaName;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
PP.Lex(Tok); // eof
|
PP.Lex(Tok); // eof
|
||||||
Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
|
Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned Parser::HandlePragmaMSSegment(llvm::StringRef PragmaName,
|
bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
|
||||||
SourceLocation PragmaLocation) {
|
SourceLocation PragmaLocation) {
|
||||||
if (Tok.isNot(tok::l_paren))
|
if (Tok.isNot(tok::l_paren)) {
|
||||||
return diag::warn_pragma_expected_lparen;
|
PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
PP.Lex(Tok); // (
|
PP.Lex(Tok); // (
|
||||||
Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
|
Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
|
||||||
llvm::StringRef SlotLabel;
|
StringRef SlotLabel;
|
||||||
if (Tok.isAnyIdentifier()) {
|
if (Tok.isAnyIdentifier()) {
|
||||||
llvm::StringRef PushPop = Tok.getIdentifierInfo()->getName();
|
StringRef PushPop = Tok.getIdentifierInfo()->getName();
|
||||||
if (PushPop == "push")
|
if (PushPop == "push")
|
||||||
Action = Sema::PSK_Push;
|
Action = Sema::PSK_Push;
|
||||||
else if (PushPop == "pop")
|
else if (PushPop == "pop")
|
||||||
Action = Sema::PSK_Pop;
|
Action = Sema::PSK_Pop;
|
||||||
else
|
else {
|
||||||
return diag::warn_pragma_expected_section_push_pop_or_name;
|
PP.Diag(PragmaLocation,
|
||||||
|
diag::warn_pragma_expected_section_push_pop_or_name)
|
||||||
|
<< PragmaName;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (Action != Sema::PSK_Reset) {
|
if (Action != Sema::PSK_Reset) {
|
||||||
PP.Lex(Tok); // push | pop
|
PP.Lex(Tok); // push | pop
|
||||||
if (Tok.is(tok::comma)) {
|
if (Tok.is(tok::comma)) {
|
||||||
|
@ -562,41 +588,64 @@ unsigned Parser::HandlePragmaMSSegment(llvm::StringRef PragmaName,
|
||||||
PP.Lex(Tok); // identifier
|
PP.Lex(Tok); // identifier
|
||||||
if (Tok.is(tok::comma))
|
if (Tok.is(tok::comma))
|
||||||
PP.Lex(Tok);
|
PP.Lex(Tok);
|
||||||
else if (Tok.isNot(tok::r_paren))
|
else if (Tok.isNot(tok::r_paren)) {
|
||||||
return diag::warn_pragma_expected_punc;
|
PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
|
||||||
|
<< PragmaName;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (Tok.isNot(tok::r_paren))
|
} else if (Tok.isNot(tok::r_paren)) {
|
||||||
return diag::warn_pragma_expected_punc;
|
PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Grab the string literal for our section name.
|
// Grab the string literal for our section name.
|
||||||
StringLiteral *SegmentName = nullptr;
|
StringLiteral *SegmentName = nullptr;
|
||||||
if (Tok.isNot(tok::r_paren)) {
|
if (Tok.isNot(tok::r_paren)) {
|
||||||
if (Tok.isNot(tok::string_literal))
|
if (Tok.isNot(tok::string_literal)) {
|
||||||
return Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
|
unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
|
||||||
diag::warn_pragma_expected_section_name :
|
diag::warn_pragma_expected_section_name :
|
||||||
diag::warn_pragma_expected_section_label_or_name :
|
diag::warn_pragma_expected_section_label_or_name :
|
||||||
diag::warn_pragma_expected_section_push_pop_or_name;
|
diag::warn_pragma_expected_section_push_pop_or_name;
|
||||||
SegmentName = cast<StringLiteral>(ParseStringLiteralExpression().get());
|
PP.Diag(PragmaLocation, DiagID) << PragmaName;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ExprResult StringResult = ParseStringLiteralExpression();
|
||||||
|
if (StringResult.isInvalid())
|
||||||
|
return false; // Already diagnosed.
|
||||||
|
SegmentName = cast<StringLiteral>(StringResult.get());
|
||||||
|
if (SegmentName->getCharByteWidth() != 1) {
|
||||||
|
PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
|
||||||
|
<< PragmaName;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// Setting section "" has no effect
|
// Setting section "" has no effect
|
||||||
if (SegmentName->getLength())
|
if (SegmentName->getLength())
|
||||||
Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
|
Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
|
||||||
}
|
}
|
||||||
if (Tok.isNot(tok::r_paren))
|
if (Tok.isNot(tok::r_paren)) {
|
||||||
return diag::warn_pragma_expected_rparen;
|
PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
PP.Lex(Tok); // )
|
PP.Lex(Tok); // )
|
||||||
if (Tok.isNot(tok::eof))
|
if (Tok.isNot(tok::eof)) {
|
||||||
return diag::warn_pragma_extra_tokens_at_eol;
|
PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
|
||||||
|
<< PragmaName;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
PP.Lex(Tok); // eof
|
PP.Lex(Tok); // eof
|
||||||
Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
|
Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
|
||||||
SegmentName, PragmaName);
|
SegmentName, PragmaName);
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned Parser::HandlePragmaMSInitSeg(llvm::StringRef PragmaName,
|
bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
|
||||||
SourceLocation PragmaLocation) {
|
SourceLocation PragmaLocation) {
|
||||||
return PP.getDiagnostics().getCustomDiagID(
|
PP.Diag(PragmaLocation,
|
||||||
DiagnosticsEngine::Error, "'#pragma %0' not implemented.");
|
PP.getDiagnostics().getCustomDiagID(
|
||||||
|
DiagnosticsEngine::Error, "'#pragma init_seg' not implemented."));
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PragmaLoopHintInfo {
|
struct PragmaLoopHintInfo {
|
||||||
|
|
|
@ -8,6 +8,8 @@ int b = 1; // expected-error {{'b' causes a section type conflict with 'a'}}
|
||||||
#pragma data_seg()
|
#pragma data_seg()
|
||||||
int c = 1;
|
int c = 1;
|
||||||
__declspec(allocate(".my_const")) int d = 1; // expected-error {{'d' causes a section type conflict with 'a'}}
|
__declspec(allocate(".my_const")) int d = 1; // expected-error {{'d' causes a section type conflict with 'a'}}
|
||||||
|
#pragma data_seg("\u") // expected-error {{\u used with no following hex digits}}
|
||||||
|
#pragma data_seg("a" L"b") // expected-warning {{expected non-wide string literal in '#pragma data_seg'}}
|
||||||
|
|
||||||
#pragma section(".my_seg", execute) // expected-note 2 {{#pragma entered her}}
|
#pragma section(".my_seg", execute) // expected-note 2 {{#pragma entered her}}
|
||||||
__declspec(allocate(".my_seg")) int int_my_seg;
|
__declspec(allocate(".my_seg")) int int_my_seg;
|
||||||
|
|
Loading…
Reference in New Issue