forked from OSchip/llvm-project
Generate a marker token when entering or leaving a submodule when building a
module. Use the marker to diagnose cases where we try to transition between submodules when not at the top level (most likely because a closing brace was missing at the end of a header file, but is also possible if submodule headers attempt to do something fundamentally non-modular, like our .def files). llvm-svn: 195543
This commit is contained in:
parent
5c6eab21eb
commit
34f30516aa
|
@ -667,8 +667,10 @@ ANNOTATION(pragma_opencl_extension)
|
|||
ANNOTATION(pragma_openmp)
|
||||
ANNOTATION(pragma_openmp_end)
|
||||
|
||||
// Annotation for module import translated from #include etc.
|
||||
// Annotations for module import translated from #include etc.
|
||||
ANNOTATION(module_include)
|
||||
ANNOTATION(module_begin)
|
||||
ANNOTATION(module_end)
|
||||
|
||||
#undef ANNOTATION
|
||||
#undef TESTING_KEYWORD
|
||||
|
|
|
@ -276,22 +276,26 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
|
|||
CLK_LexAfterModuleImport
|
||||
} CurLexerKind;
|
||||
|
||||
/// \brief True if the current lexer is for a submodule.
|
||||
bool CurIsSubmodule;
|
||||
|
||||
/// IncludeMacroStack - This keeps track of the stack of files currently
|
||||
/// \#included, and macros currently being expanded from, not counting
|
||||
/// CurLexer/CurTokenLexer.
|
||||
struct IncludeStackInfo {
|
||||
enum CurLexerKind CurLexerKind;
|
||||
bool IsSubmodule;
|
||||
Lexer *TheLexer;
|
||||
PTHLexer *ThePTHLexer;
|
||||
PreprocessorLexer *ThePPLexer;
|
||||
TokenLexer *TheTokenLexer;
|
||||
const DirectoryLookup *TheDirLookup;
|
||||
|
||||
IncludeStackInfo(enum CurLexerKind K, Lexer *L, PTHLexer* P,
|
||||
PreprocessorLexer* PPL,
|
||||
TokenLexer* TL, const DirectoryLookup *D)
|
||||
: CurLexerKind(K), TheLexer(L), ThePTHLexer(P), ThePPLexer(PPL),
|
||||
TheTokenLexer(TL), TheDirLookup(D) {}
|
||||
IncludeStackInfo(enum CurLexerKind K, bool SM, Lexer *L, PTHLexer *P,
|
||||
PreprocessorLexer *PPL, TokenLexer *TL,
|
||||
const DirectoryLookup *D)
|
||||
: CurLexerKind(K), IsSubmodule(SM), TheLexer(L), ThePTHLexer(P),
|
||||
ThePPLexer(PPL), TheTokenLexer(TL), TheDirLookup(D) {}
|
||||
};
|
||||
std::vector<IncludeStackInfo> IncludeMacroStack;
|
||||
|
||||
|
@ -662,7 +666,7 @@ public:
|
|||
/// start lexing tokens from it instead of the current buffer. Emit an error
|
||||
/// and don't enter the file on error.
|
||||
void EnterSourceFile(FileID CurFileID, const DirectoryLookup *Dir,
|
||||
SourceLocation Loc);
|
||||
SourceLocation Loc, bool IsSubmodule = false);
|
||||
|
||||
/// EnterMacro - Add a Macro to the top of the include stack and start lexing
|
||||
/// tokens from it instead of the current buffer. Args specifies the
|
||||
|
@ -1155,6 +1159,9 @@ private:
|
|||
IdentifierInfo *Ident__abnormal_termination,
|
||||
*Ident___abnormal_termination,
|
||||
*Ident_AbnormalTermination;
|
||||
|
||||
const char *getCurLexerEndPos();
|
||||
|
||||
public:
|
||||
void PoisonSEHIdentifiers(bool Poison = true); // Borland
|
||||
|
||||
|
@ -1265,6 +1272,7 @@ private:
|
|||
|
||||
void PushIncludeMacroStack() {
|
||||
IncludeMacroStack.push_back(IncludeStackInfo(CurLexerKind,
|
||||
CurIsSubmodule,
|
||||
CurLexer.take(),
|
||||
CurPTHLexer.take(),
|
||||
CurPPLexer,
|
||||
|
@ -1280,6 +1288,7 @@ private:
|
|||
CurTokenLexer.reset(IncludeMacroStack.back().TheTokenLexer);
|
||||
CurDirLookup = IncludeMacroStack.back().TheDirLookup;
|
||||
CurLexerKind = IncludeMacroStack.back().CurLexerKind;
|
||||
CurIsSubmodule = IncludeMacroStack.back().IsSubmodule;
|
||||
IncludeMacroStack.pop_back();
|
||||
}
|
||||
|
||||
|
@ -1380,11 +1389,13 @@ private:
|
|||
|
||||
/// EnterSourceFileWithLexer - Add a lexer to the top of the include stack and
|
||||
/// start lexing tokens from it instead of the current buffer.
|
||||
void EnterSourceFileWithLexer(Lexer *TheLexer, const DirectoryLookup *Dir);
|
||||
void EnterSourceFileWithLexer(Lexer *TheLexer, const DirectoryLookup *Dir,
|
||||
bool IsSubmodule = false);
|
||||
|
||||
/// EnterSourceFileWithPTH - Add a lexer to the top of the include stack and
|
||||
/// start getting tokens from it using the PTH cache.
|
||||
void EnterSourceFileWithPTH(PTHLexer *PL, const DirectoryLookup *Dir);
|
||||
void EnterSourceFileWithPTH(PTHLexer *PL, const DirectoryLookup *Dir,
|
||||
bool IsSubmodule = false);
|
||||
|
||||
/// \brief Set the file ID for the preprocessor predefines.
|
||||
void setPredefinesFileID(FileID FID) {
|
||||
|
|
|
@ -408,6 +408,14 @@ private:
|
|||
Tok.setKind(tok::eof);
|
||||
}
|
||||
|
||||
/// \brief Determine if we're at the end of the file or at a transition
|
||||
/// between modules.
|
||||
bool isEofOrEom() {
|
||||
tok::TokenKind Kind = Tok.getKind();
|
||||
return Kind == tok::eof || Kind == tok::annot_module_begin ||
|
||||
Kind == tok::annot_module_end || Kind == tok::annot_module_include;
|
||||
}
|
||||
|
||||
/// \brief Handle the annotation token produced for #pragma unused(...)
|
||||
void HandlePragmaUnused();
|
||||
|
||||
|
|
|
@ -657,7 +657,9 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok,
|
|||
// -traditional-cpp the lexer keeps /all/ whitespace, including comments.
|
||||
SourceLocation StartLoc = Tok.getLocation();
|
||||
Callbacks->MoveToLine(StartLoc.getLocWithOffset(Tok.getLength()));
|
||||
} else if (Tok.is(tok::annot_module_include)) {
|
||||
} else if (Tok.is(tok::annot_module_include) ||
|
||||
Tok.is(tok::annot_module_begin) ||
|
||||
Tok.is(tok::annot_module_end)) {
|
||||
// PrintPPOutputPPCallbacks::InclusionDirective handles producing
|
||||
// appropriate output here. Ignore this token entirely.
|
||||
PP.Lex(Tok);
|
||||
|
|
|
@ -1389,6 +1389,19 @@ bool Preprocessor::ConcatenateIncludeName(
|
|||
return true;
|
||||
}
|
||||
|
||||
/// \brief Push a token onto the token stream containing an annotation.
|
||||
static void EnterAnnotationToken(Preprocessor &PP,
|
||||
SourceLocation Begin, SourceLocation End,
|
||||
tok::TokenKind Kind, void *AnnotationVal) {
|
||||
Token *Tok = new Token[1];
|
||||
Tok[0].startToken();
|
||||
Tok[0].setKind(Kind);
|
||||
Tok[0].setLocation(Begin);
|
||||
Tok[0].setAnnotationEndLoc(End);
|
||||
Tok[0].setAnnotationValue(AnnotationVal);
|
||||
PP.EnterTokenStream(Tok, 1, true, true);
|
||||
}
|
||||
|
||||
/// HandleIncludeDirective - The "\#include" tokens have just been read, read
|
||||
/// the file to be included from the lexer, then include it! This is a common
|
||||
/// routine with functionality shared between \#include, \#include_next and
|
||||
|
@ -1639,13 +1652,8 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
|
|||
// make the module visible.
|
||||
// FIXME: Produce this as the current token directly, rather than
|
||||
// allocating a new token for it.
|
||||
Token *Tok = new Token[1];
|
||||
Tok[0].startToken();
|
||||
Tok[0].setKind(tok::annot_module_include);
|
||||
Tok[0].setLocation(HashLoc);
|
||||
Tok[0].setAnnotationEndLoc(End);
|
||||
Tok[0].setAnnotationValue(Imported);
|
||||
EnterTokenStream(Tok, 1, true, true);
|
||||
EnterAnnotationToken(*this, HashLoc, End, tok::annot_module_include,
|
||||
Imported);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1692,8 +1700,23 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
|
|||
FileID FID = SourceMgr.createFileID(File, IncludePos, FileCharacter);
|
||||
assert(!FID.isInvalid() && "Expected valid file ID");
|
||||
|
||||
// Finally, if all is good, enter the new file!
|
||||
EnterSourceFile(FID, CurDir, FilenameTok.getLocation());
|
||||
// Determine if we're switching to building a new submodule, and which one.
|
||||
ModuleMap::KnownHeader BuildingModule;
|
||||
if (getLangOpts().Modules && !getLangOpts().CurrentModule.empty()) {
|
||||
Module *RequestingModule = getModuleForLocation(FilenameLoc);
|
||||
BuildingModule =
|
||||
HeaderInfo.getModuleMap().findModuleForHeader(File, RequestingModule);
|
||||
}
|
||||
|
||||
// If all is good, enter the new file!
|
||||
EnterSourceFile(FID, CurDir, FilenameTok.getLocation(),
|
||||
static_cast<bool>(BuildingModule));
|
||||
|
||||
// If we're walking into another part of the same module, let the parser
|
||||
// know that any future declarations are within that other submodule.
|
||||
if (BuildingModule)
|
||||
EnterAnnotationToken(*this, HashLoc, End, tok::annot_module_begin,
|
||||
BuildingModule.getModule());
|
||||
}
|
||||
|
||||
/// HandleIncludeNextDirective - Implements \#include_next.
|
||||
|
|
|
@ -69,7 +69,7 @@ PreprocessorLexer *Preprocessor::getCurrentFileLexer() const {
|
|||
/// EnterSourceFile - Add a source file to the top of the include stack and
|
||||
/// start lexing tokens from it instead of the current buffer.
|
||||
void Preprocessor::EnterSourceFile(FileID FID, const DirectoryLookup *CurDir,
|
||||
SourceLocation Loc) {
|
||||
SourceLocation Loc, bool IsSubmodule) {
|
||||
assert(!CurTokenLexer && "Cannot #include a file inside a macro!");
|
||||
++NumEnteredSourceFiles;
|
||||
|
||||
|
@ -78,7 +78,7 @@ void Preprocessor::EnterSourceFile(FileID FID, const DirectoryLookup *CurDir,
|
|||
|
||||
if (PTH) {
|
||||
if (PTHLexer *PL = PTH->CreateLexer(FID)) {
|
||||
EnterSourceFileWithPTH(PL, CurDir);
|
||||
EnterSourceFileWithPTH(PL, CurDir, IsSubmodule);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -101,14 +101,16 @@ void Preprocessor::EnterSourceFile(FileID FID, const DirectoryLookup *CurDir,
|
|||
CodeCompletionFileLoc.getLocWithOffset(CodeCompletionOffset);
|
||||
}
|
||||
|
||||
EnterSourceFileWithLexer(new Lexer(FID, InputFile, *this), CurDir);
|
||||
EnterSourceFileWithLexer(new Lexer(FID, InputFile, *this), CurDir,
|
||||
IsSubmodule);
|
||||
return;
|
||||
}
|
||||
|
||||
/// EnterSourceFileWithLexer - Add a source file to the top of the include stack
|
||||
/// and start lexing tokens from it instead of the current buffer.
|
||||
void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer,
|
||||
const DirectoryLookup *CurDir) {
|
||||
const DirectoryLookup *CurDir,
|
||||
bool IsSubmodule) {
|
||||
|
||||
// Add the current lexer to the include stack.
|
||||
if (CurPPLexer || CurTokenLexer)
|
||||
|
@ -117,6 +119,7 @@ void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer,
|
|||
CurLexer.reset(TheLexer);
|
||||
CurPPLexer = TheLexer;
|
||||
CurDirLookup = CurDir;
|
||||
CurIsSubmodule = IsSubmodule;
|
||||
if (CurLexerKind != CLK_LexAfterModuleImport)
|
||||
CurLexerKind = CLK_Lexer;
|
||||
|
||||
|
@ -133,7 +136,8 @@ void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer,
|
|||
/// EnterSourceFileWithPTH - Add a source file to the top of the include stack
|
||||
/// and start getting tokens from it using the PTH cache.
|
||||
void Preprocessor::EnterSourceFileWithPTH(PTHLexer *PL,
|
||||
const DirectoryLookup *CurDir) {
|
||||
const DirectoryLookup *CurDir,
|
||||
bool IsSubmodule) {
|
||||
|
||||
if (CurPPLexer || CurTokenLexer)
|
||||
PushIncludeMacroStack();
|
||||
|
@ -141,6 +145,7 @@ void Preprocessor::EnterSourceFileWithPTH(PTHLexer *PL,
|
|||
CurDirLookup = CurDir;
|
||||
CurPTHLexer.reset(PL);
|
||||
CurPPLexer = CurPTHLexer.get();
|
||||
CurIsSubmodule = IsSubmodule;
|
||||
if (CurLexerKind != CLK_LexAfterModuleImport)
|
||||
CurLexerKind = CLK_PTHLexer;
|
||||
|
||||
|
@ -244,6 +249,29 @@ void Preprocessor::PropagateLineStartLeadingSpaceInfo(Token &Result) {
|
|||
// but it might if they're empty?
|
||||
}
|
||||
|
||||
/// \brief Determine the location to use as the end of the buffer for a lexer.
|
||||
///
|
||||
/// If the file ends with a newline, form the EOF token on the newline itself,
|
||||
/// rather than "on the line following it", which doesn't exist. This makes
|
||||
/// diagnostics relating to the end of file include the last file that the user
|
||||
/// actually typed, which is goodness.
|
||||
const char *Preprocessor::getCurLexerEndPos() {
|
||||
const char *EndPos = CurLexer->BufferEnd;
|
||||
if (EndPos != CurLexer->BufferStart &&
|
||||
(EndPos[-1] == '\n' || EndPos[-1] == '\r')) {
|
||||
--EndPos;
|
||||
|
||||
// Handle \n\r and \r\n:
|
||||
if (EndPos != CurLexer->BufferStart &&
|
||||
(EndPos[-1] == '\n' || EndPos[-1] == '\r') &&
|
||||
EndPos[-1] != EndPos[0])
|
||||
--EndPos;
|
||||
}
|
||||
|
||||
return EndPos;
|
||||
}
|
||||
|
||||
|
||||
/// HandleEndOfFile - This callback is invoked when the lexer hits the end of
|
||||
/// the current file. This either returns the EOF token or pops a level off
|
||||
/// the include stack and keeps going.
|
||||
|
@ -343,6 +371,18 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
|
|||
if (Callbacks && !isEndOfMacro && CurPPLexer)
|
||||
ExitedFID = CurPPLexer->getFileID();
|
||||
|
||||
// If this file corresponded to a submodule, notify the parser that we've
|
||||
// left that submodule.
|
||||
bool LeavingSubmodule = CurIsSubmodule && CurLexer;
|
||||
if (LeavingSubmodule) {
|
||||
const char *EndPos = getCurLexerEndPos();
|
||||
Result.startToken();
|
||||
CurLexer->BufferPtr = EndPos;
|
||||
CurLexer->FormTokenWithChars(Result, EndPos, tok::annot_module_end);
|
||||
Result.setAnnotationEndLoc(Result.getLocation());
|
||||
Result.setAnnotationValue(0);
|
||||
}
|
||||
|
||||
// We're done with the #included file.
|
||||
RemoveTopOfLexerStack();
|
||||
|
||||
|
@ -357,27 +397,13 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
|
|||
PPCallbacks::ExitFile, FileType, ExitedFID);
|
||||
}
|
||||
|
||||
// Client should lex another token.
|
||||
return false;
|
||||
// Client should lex another token unless we generated an EOM.
|
||||
return LeavingSubmodule;
|
||||
}
|
||||
|
||||
// If the file ends with a newline, form the EOF token on the newline itself,
|
||||
// rather than "on the line following it", which doesn't exist. This makes
|
||||
// diagnostics relating to the end of file include the last file that the user
|
||||
// actually typed, which is goodness.
|
||||
// If this is the end of the main file, form an EOF token.
|
||||
if (CurLexer) {
|
||||
const char *EndPos = CurLexer->BufferEnd;
|
||||
if (EndPos != CurLexer->BufferStart &&
|
||||
(EndPos[-1] == '\n' || EndPos[-1] == '\r')) {
|
||||
--EndPos;
|
||||
|
||||
// Handle \n\r and \r\n:
|
||||
if (EndPos != CurLexer->BufferStart &&
|
||||
(EndPos[-1] == '\n' || EndPos[-1] == '\r') &&
|
||||
EndPos[-1] != EndPos[0])
|
||||
--EndPos;
|
||||
}
|
||||
|
||||
const char *EndPos = getCurLexerEndPos();
|
||||
Result.startToken();
|
||||
CurLexer->BufferPtr = EndPos;
|
||||
CurLexer->FormTokenWithChars(Result, EndPos, tok::eof);
|
||||
|
|
|
@ -67,8 +67,8 @@ Preprocessor::Preprocessor(IntrusiveRefCntPtr<PreprocessorOptions> PPOpts,
|
|||
CodeComplete(0), CodeCompletionFile(0), CodeCompletionOffset(0),
|
||||
LastTokenWasAt(false), ModuleImportExpectsIdentifier(false),
|
||||
CodeCompletionReached(0), SkipMainFilePreamble(0, true), CurPPLexer(0),
|
||||
CurDirLookup(0), CurLexerKind(CLK_Lexer), Callbacks(0),
|
||||
MacroArgCache(0), Record(0), MIChainHead(0), MICache(0),
|
||||
CurDirLookup(0), CurLexerKind(CLK_Lexer), CurIsSubmodule(false),
|
||||
Callbacks(0), MacroArgCache(0), Record(0), MIChainHead(0), MICache(0),
|
||||
DeserialMIChainHead(0) {
|
||||
OwnsHeaderSearch = OwnsHeaders;
|
||||
|
||||
|
|
|
@ -580,6 +580,9 @@ bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2,
|
|||
|
||||
switch (Tok.getKind()) {
|
||||
case tok::eof:
|
||||
case tok::annot_module_begin:
|
||||
case tok::annot_module_end:
|
||||
case tok::annot_module_include:
|
||||
// Ran out of tokens.
|
||||
return false;
|
||||
|
||||
|
@ -965,6 +968,9 @@ bool Parser::ConsumeAndStoreInitializer(CachedTokens &Toks,
|
|||
goto consume_token;
|
||||
|
||||
case tok::eof:
|
||||
case tok::annot_module_begin:
|
||||
case tok::annot_module_end:
|
||||
case tok::annot_module_include:
|
||||
// Ran out of tokens.
|
||||
return false;
|
||||
|
||||
|
|
|
@ -1561,6 +1561,9 @@ void Parser::SkipMalformedDecl() {
|
|||
break;
|
||||
|
||||
case tok::eof:
|
||||
case tok::annot_module_begin:
|
||||
case tok::annot_module_end:
|
||||
case tok::annot_module_include:
|
||||
return;
|
||||
|
||||
default:
|
||||
|
@ -3371,7 +3374,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
|
|||
SmallVector<Decl *, 32> FieldDecls;
|
||||
|
||||
// While we still have something to read, read the declarations in the struct.
|
||||
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
|
||||
while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
|
||||
// Each iteration of this loop reads one struct-declaration.
|
||||
|
||||
// Check for extraneous top-level semicolon.
|
||||
|
|
|
@ -195,7 +195,7 @@ void Parser::ParseInnerNamespace(std::vector<SourceLocation>& IdentLoc,
|
|||
ParsedAttributes& attrs,
|
||||
BalancedDelimiterTracker &Tracker) {
|
||||
if (index == Ident.size()) {
|
||||
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
|
||||
while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
|
||||
ParsedAttributesWithRange attrs(AttrFactory);
|
||||
MaybeParseCXX11Attributes(attrs);
|
||||
MaybeParseMicrosoftAttributes(attrs);
|
||||
|
@ -318,7 +318,7 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) {
|
|||
|
||||
BalancedDelimiterTracker T(*this, tok::l_brace);
|
||||
T.consumeOpen();
|
||||
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
|
||||
while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
|
||||
ParsedAttributesWithRange attrs(AttrFactory);
|
||||
MaybeParseCXX11Attributes(attrs);
|
||||
MaybeParseMicrosoftAttributes(attrs);
|
||||
|
@ -2452,7 +2452,7 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction,
|
|||
// a top-level comma always ends the initializer expression.
|
||||
const Token &Next = NextToken();
|
||||
if (IsFunction || Next.is(tok::semi) || Next.is(tok::comma) ||
|
||||
Next.is(tok::eof)) {
|
||||
Next.is(tok::eof)) {
|
||||
if (IsFunction)
|
||||
Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration)
|
||||
<< 1 /* delete */;
|
||||
|
@ -2597,7 +2597,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
|
|||
|
||||
if (TagDecl) {
|
||||
// While we still have something to read, read the member-declarations.
|
||||
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
|
||||
while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
|
||||
// Each iteration of this loop reads one member-declaration.
|
||||
|
||||
if (getLangOpts().MicrosoftExt && (Tok.is(tok::kw___if_exists) ||
|
||||
|
@ -3420,7 +3420,7 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType,
|
|||
return;
|
||||
}
|
||||
|
||||
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
|
||||
while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
|
||||
// __if_exists, __if_not_exists can nest.
|
||||
if ((Tok.is(tok::kw___if_exists) || Tok.is(tok::kw___if_not_exists))) {
|
||||
ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, CurAS);
|
||||
|
|
|
@ -512,7 +512,7 @@ bool Parser::ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs,
|
|||
return false;
|
||||
}
|
||||
|
||||
while (Tok.isNot(tok::eof)) {
|
||||
while (!isEofOrEom()) {
|
||||
trailingComma = false;
|
||||
// If we know that this cannot be a designation, just parse the nested
|
||||
// initializer directly.
|
||||
|
|
|
@ -423,7 +423,7 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
|
|||
}
|
||||
|
||||
// If we got to the end of the file, exit the loop.
|
||||
if (Tok.is(tok::eof))
|
||||
if (isEofOrEom())
|
||||
break;
|
||||
|
||||
// Code completion within an Objective-C interface.
|
||||
|
@ -1289,7 +1289,7 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
|
|||
BalancedDelimiterTracker T(*this, tok::l_brace);
|
||||
T.consumeOpen();
|
||||
// While we still have something to read, read the instance variables.
|
||||
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
|
||||
while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
|
||||
// Each iteration of this loop reads one objc-instance-variable-decl.
|
||||
|
||||
// Check for extraneous top-level semicolon.
|
||||
|
@ -1582,7 +1582,7 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) {
|
|||
|
||||
{
|
||||
ObjCImplParsingDataRAII ObjCImplParsing(*this, ObjCImpDecl);
|
||||
while (!ObjCImplParsing.isFinished() && Tok.isNot(tok::eof)) {
|
||||
while (!ObjCImplParsing.isFinished() && !isEofOrEom()) {
|
||||
ParsedAttributesWithRange attrs(AttrFactory);
|
||||
MaybeParseCXX11Attributes(attrs);
|
||||
MaybeParseMicrosoftAttributes(attrs);
|
||||
|
@ -1612,7 +1612,7 @@ Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) {
|
|||
Parser::ObjCImplParsingDataRAII::~ObjCImplParsingDataRAII() {
|
||||
if (!Finished) {
|
||||
finish(P.Tok.getLocation());
|
||||
if (P.Tok.is(tok::eof)) {
|
||||
if (P.isEofOrEom()) {
|
||||
P.Diag(P.Tok, diag::err_objc_missing_end)
|
||||
<< FixItHint::CreateInsertion(P.Tok.getLocation(), "\n@end\n");
|
||||
P.Diag(Dcl->getLocStart(), diag::note_objc_container_start)
|
||||
|
|
|
@ -890,7 +890,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
|
|||
Stmts.push_back(R.release());
|
||||
}
|
||||
|
||||
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
|
||||
while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
|
||||
if (Tok.is(tok::annot_pragma_unused)) {
|
||||
HandlePragmaUnused();
|
||||
continue;
|
||||
|
@ -2058,7 +2058,7 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) {
|
|||
SourceLocation TokLoc = Tok.getLocation();
|
||||
do {
|
||||
// If we hit EOF, we're done, period.
|
||||
if (Tok.is(tok::eof))
|
||||
if (isEofOrEom())
|
||||
break;
|
||||
|
||||
if (!InAsmComment && Tok.is(tok::semi)) {
|
||||
|
|
|
@ -288,7 +288,7 @@ bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, SkipUntilFlags Flags) {
|
|||
if (Toks.size() == 1 && Toks[0] == tok::eof &&
|
||||
!HasFlagsSet(Flags, StopAtSemi) &&
|
||||
!HasFlagsSet(Flags, StopAtCodeCompletion)) {
|
||||
while (Tok.getKind() != tok::eof)
|
||||
while (Tok.isNot(tok::eof))
|
||||
ConsumeAnyToken();
|
||||
return true;
|
||||
}
|
||||
|
@ -298,6 +298,14 @@ bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, SkipUntilFlags Flags) {
|
|||
// Ran out of tokens.
|
||||
return false;
|
||||
|
||||
case tok::annot_module_begin:
|
||||
case tok::annot_module_end:
|
||||
case tok::annot_module_include:
|
||||
// Stop before we change submodules. They generally indicate a "good"
|
||||
// place to pick up parsing again (except in the special case where
|
||||
// we're trying to skip to EOF).
|
||||
return false;
|
||||
|
||||
case tok::code_completion:
|
||||
if (!HasFlagsSet(Flags, StopAtCodeCompletion))
|
||||
ConsumeToken();
|
||||
|
@ -576,8 +584,10 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
|
|||
|
||||
// Skip over the EOF token, flagging end of previous input for incremental
|
||||
// processing
|
||||
if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::eof))
|
||||
if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::eof)) {
|
||||
ConsumeToken();
|
||||
return false;
|
||||
}
|
||||
|
||||
Result = DeclGroupPtrTy();
|
||||
switch (Tok.getKind()) {
|
||||
|
@ -592,6 +602,12 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
|
|||
ConsumeToken();
|
||||
return false;
|
||||
|
||||
case tok::annot_module_begin:
|
||||
case tok::annot_module_end:
|
||||
// FIXME: Update visibility based on the submodule we're in.
|
||||
ConsumeToken();
|
||||
return false;
|
||||
|
||||
case tok::eof:
|
||||
// Late template parsing can begin.
|
||||
if (getLangOpts().DelayedTemplateParsing)
|
||||
|
@ -1917,7 +1933,8 @@ void Parser::ParseMicrosoftIfExistsExternalDeclaration() {
|
|||
}
|
||||
|
||||
// Parse the declarations.
|
||||
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
|
||||
// FIXME: Support module import within __if_exists?
|
||||
while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
|
||||
ParsedAttributesWithRange attrs(AttrFactory);
|
||||
MaybeParseCXX11Attributes(attrs);
|
||||
MaybeParseMicrosoftAttributes(attrs);
|
||||
|
@ -1980,7 +1997,7 @@ bool BalancedDelimiterTracker::diagnoseOverflow() {
|
|||
P.Diag(P.Tok, diag::err_bracket_depth_exceeded)
|
||||
<< P.getLangOpts().BracketDepth;
|
||||
P.Diag(P.Tok, diag::note_bracket_depth);
|
||||
P.SkipUntil(tok::eof);
|
||||
P.cutOffParsing();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
void f() {
|
|
@ -0,0 +1 @@
|
|||
}
|
|
@ -0,0 +1,3 @@
|
|||
struct S {
|
||||
#include "b2.h"
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
void g() {}
|
|
@ -0,0 +1,8 @@
|
|||
module a {
|
||||
module a1 { header "a1.h" }
|
||||
module a2 { header "a2.h" }
|
||||
}
|
||||
module b {
|
||||
module b1 { header "b1.h" }
|
||||
module b2 { header "b2.h" }
|
||||
}
|
|
@ -83,6 +83,6 @@ int getNotInModule() {
|
|||
return not_in_module;
|
||||
}
|
||||
|
||||
void includeNotAtTopLevel() {
|
||||
#include <NoUmbrella/A.h> // expected-warning {{treating #include as an import}} expected-error {{expected expression}}
|
||||
}
|
||||
void includeNotAtTopLevel() { // expected-note {{to match this '{'}}
|
||||
#include <NoUmbrella/A.h> // expected-warning {{treating #include as an import}} expected-error {{expected '}'}}
|
||||
} // expected-error {{extraneous closing brace}}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
// RUN: rm -rf %t
|
||||
// RUN: not %clang_cc1 -fmodules -fmodules-cache-path=%t -I %S/Inputs/malformed -DHEADER="a1.h" %s 2>&1 | FileCheck %s --check-prefix=CHECK-A
|
||||
// RUN: not %clang_cc1 -fmodules -fmodules-cache-path=%t -I %S/Inputs/malformed -DHEADER="b1.h" %s 2>&1 | FileCheck %s --check-prefix=CHECK-B
|
||||
|
||||
#define STR2(x) #x
|
||||
#define STR(x) STR2(x)
|
||||
#include STR(HEADER)
|
||||
|
||||
// CHECK-A: While building module 'a'
|
||||
// CHECK-A: a1.h:1:{{.*}} error: expected '}'
|
||||
// CHECK-A: a1.h:1:{{.*}} note: to match this '{'
|
||||
//
|
||||
// CHECK-A: While building module 'a'
|
||||
// CHECK-A: a2.h:1:{{.*}} error: extraneous closing brace
|
||||
|
||||
// CHECK-B: While building module 'b'
|
||||
// CHECK-B: b1.h:2:{{.*}} error: expected '}'
|
||||
// CHECK-B: b1.h:1:{{.*}} note: to match this '{'
|
||||
// CHECK-B: b1.h:3:{{.*}} error: extraneous closing brace ('}')
|
||||
//
|
||||
// CHECK-B: While building module 'b'
|
||||
// CHECK-B: b2.h:1:{{.*}} error: redefinition of 'g'
|
||||
// CHECK-B: b2.h:1:{{.*}} note: previous definition is here
|
Loading…
Reference in New Issue