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:
Reid Kleckner 2014-07-18 00:13:16 +00:00
parent 874648372c
commit fadb218b32
4 changed files with 109 additions and 56 deletions

View File

@ -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">,

View File

@ -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...

View File

@ -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 {

View File

@ -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;