summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Parse/Parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse/Parser.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/Parser.cpp184
1 files changed, 143 insertions, 41 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp
index 455139b..457dd36 100644
--- a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp
@@ -103,8 +103,10 @@ Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies)
PP.AddPragmaHandler(OpenMPHandler.get());
if (getLangOpts().MicrosoftExt) {
- MSCommentHandler.reset(new PragmaCommentHandler());
+ MSCommentHandler.reset(new PragmaCommentHandler(actions));
PP.AddPragmaHandler(MSCommentHandler.get());
+ MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(actions));
+ PP.AddPragmaHandler(MSDetectMismatchHandler.get());
}
CommentSemaHandler.reset(new ActionCommentHandler(actions));
@@ -188,7 +190,7 @@ bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID,
Diag(Tok, DiagID) << Msg;
if (SkipToTok != tok::unknown)
- SkipUntil(SkipToTok);
+ SkipUntil(SkipToTok, StopAtSemi);
return true;
}
@@ -251,16 +253,19 @@ void Parser::ConsumeExtraSemi(ExtraSemiKind Kind, unsigned TST) {
// Error recovery.
//===----------------------------------------------------------------------===//
+static bool HasFlagsSet(Parser::SkipUntilFlags L, Parser::SkipUntilFlags R) {
+ return (static_cast<unsigned>(L) & static_cast<unsigned>(R)) != 0;
+}
+
/// SkipUntil - Read tokens until we get to the specified token, then consume
-/// it (unless DontConsume is true). Because we cannot guarantee that the
+/// it (unless no flag StopBeforeMatch). Because we cannot guarantee that the
/// token will ever occur, this skips to the next token, or to some likely
/// good stopping point. If StopAtSemi is true, skipping will stop at a ';'
/// character.
///
/// If SkipUntil finds the specified token, it returns true, otherwise it
/// returns false.
-bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, bool StopAtSemi,
- bool DontConsume, bool StopAtCodeCompletion) {
+bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, SkipUntilFlags Flags) {
// We always want this function to skip at least one token if the first token
// isn't T and if not at EOF.
bool isFirstTokenSkipped = true;
@@ -268,7 +273,7 @@ bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, bool StopAtSemi,
// If we found one of the tokens, stop and return true.
for (unsigned i = 0, NumToks = Toks.size(); i != NumToks; ++i) {
if (Tok.is(Toks[i])) {
- if (DontConsume) {
+ if (HasFlagsSet(Flags, StopBeforeMatch)) {
// Noop, don't consume the token.
} else {
ConsumeAnyToken();
@@ -277,30 +282,50 @@ bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, bool StopAtSemi,
}
}
+ // Important special case: The caller has given up and just wants us to
+ // skip the rest of the file. Do this without recursing, since we can
+ // get here precisely because the caller detected too much recursion.
+ if (Toks.size() == 1 && Toks[0] == tok::eof &&
+ !HasFlagsSet(Flags, StopAtSemi) &&
+ !HasFlagsSet(Flags, StopAtCodeCompletion)) {
+ while (Tok.getKind() != tok::eof)
+ ConsumeAnyToken();
+ return true;
+ }
+
switch (Tok.getKind()) {
case tok::eof:
// Ran out of tokens.
return false;
case tok::code_completion:
- if (!StopAtCodeCompletion)
+ if (!HasFlagsSet(Flags, StopAtCodeCompletion))
ConsumeToken();
return false;
case tok::l_paren:
// Recursively skip properly-nested parens.
ConsumeParen();
- SkipUntil(tok::r_paren, false, false, StopAtCodeCompletion);
+ if (HasFlagsSet(Flags, StopAtCodeCompletion))
+ SkipUntil(tok::r_paren, StopAtCodeCompletion);
+ else
+ SkipUntil(tok::r_paren);
break;
case tok::l_square:
// Recursively skip properly-nested square brackets.
ConsumeBracket();
- SkipUntil(tok::r_square, false, false, StopAtCodeCompletion);
+ if (HasFlagsSet(Flags, StopAtCodeCompletion))
+ SkipUntil(tok::r_square, StopAtCodeCompletion);
+ else
+ SkipUntil(tok::r_square);
break;
case tok::l_brace:
// Recursively skip properly-nested braces.
ConsumeBrace();
- SkipUntil(tok::r_brace, false, false, StopAtCodeCompletion);
+ if (HasFlagsSet(Flags, StopAtCodeCompletion))
+ SkipUntil(tok::r_brace, StopAtCodeCompletion);
+ else
+ SkipUntil(tok::r_brace);
break;
// Okay, we found a ']' or '}' or ')', which we think should be balanced.
@@ -333,7 +358,7 @@ bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, bool StopAtSemi,
break;
case tok::semi:
- if (StopAtSemi)
+ if (HasFlagsSet(Flags, StopAtSemi))
return false;
// FALL THROUGH.
default:
@@ -410,11 +435,6 @@ Parser::~Parser() {
for (unsigned i = 0, e = NumCachedScopes; i != e; ++i)
delete ScopeCache[i];
- // Free LateParsedTemplatedFunction nodes.
- for (LateParsedTemplateMapT::iterator it = LateParsedTemplateMap.begin();
- it != LateParsedTemplateMap.end(); ++it)
- delete it->second;
-
// Remove the pragma handlers we installed.
PP.RemovePragmaHandler(AlignHandler.get());
AlignHandler.reset();
@@ -444,6 +464,8 @@ Parser::~Parser() {
if (getLangOpts().MicrosoftExt) {
PP.RemovePragmaHandler(MSCommentHandler.get());
MSCommentHandler.reset();
+ PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
+ MSDetectMismatchHandler.reset();
}
PP.RemovePragmaHandler("STDC", FPContractHandler.get());
@@ -477,6 +499,7 @@ void Parser::Initialize() {
Ident_instancetype = 0;
Ident_final = 0;
+ Ident_sealed = 0;
Ident_override = 0;
Ident_super = &PP.getIdentifierTable().get("super");
@@ -484,6 +507,7 @@ void Parser::Initialize() {
if (getLangOpts().AltiVec) {
Ident_vector = &PP.getIdentifierTable().get("vector");
Ident_pixel = &PP.getIdentifierTable().get("pixel");
+ Ident_bool = &PP.getIdentifierTable().get("bool");
}
Ident_introduced = 0;
@@ -555,19 +579,30 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::eof))
ConsumeToken();
- while (Tok.is(tok::annot_pragma_unused))
+ Result = DeclGroupPtrTy();
+ switch (Tok.getKind()) {
+ case tok::annot_pragma_unused:
HandlePragmaUnused();
+ return false;
- Result = DeclGroupPtrTy();
- if (Tok.is(tok::eof)) {
+ case tok::annot_module_include:
+ Actions.ActOnModuleInclude(Tok.getLocation(),
+ reinterpret_cast<Module *>(
+ Tok.getAnnotationValue()));
+ ConsumeToken();
+ return false;
+
+ case tok::eof:
// Late template parsing can begin.
if (getLangOpts().DelayedTemplateParsing)
Actions.SetLateTemplateParser(LateTemplateParserCallback, this);
if (!PP.isIncrementalProcessingEnabled())
Actions.ActOnEndOfTranslationUnit();
//else don't tell Sema that we ended parsing: more input might come.
-
return true;
+
+ default:
+ break;
}
ParsedAttributesWithRange attrs(AttrFactory);
@@ -840,6 +875,12 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs,
// Parse the common declaration-specifiers piece.
ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS, DSC_top_level);
+ // If we had a free-standing type definition with a missing semicolon, we
+ // may get this far before the problem becomes obvious.
+ if (DS.hasTagDefinition() &&
+ DiagnoseMissingSemiAfterTagDefinition(DS, AS, DSC_top_level))
+ return DeclGroupPtrTy();
+
// C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
// declaration-specifiers init-declarator-list[opt] ';'
if (Tok.is(tok::semi)) {
@@ -908,6 +949,26 @@ Parser::ParseDeclarationOrFunctionDefinition(ParsedAttributesWithRange &attrs,
}
}
+
+static inline bool isFunctionDeclaratorRequiringReturnTypeDeduction(
+ const Declarator &D) {
+ if (!D.isFunctionDeclarator() || !D.getDeclSpec().containsPlaceholderType())
+ return false;
+ for (unsigned I = 0, E = D.getNumTypeObjects(); I != E; ++I) {
+ unsigned chunkIndex = E - I - 1;
+ const DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex);
+ if (DeclType.Kind == DeclaratorChunk::Function) {
+ const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
+ if (!FTI.hasTrailingReturnType())
+ return true;
+ QualType TrailingRetType = FTI.getTrailingReturnType().get();
+ return TrailingRetType->getCanonicalTypeInternal()
+ ->getContainedAutoType();
+ }
+ }
+ return false;
+}
+
/// ParseFunctionDefinition - We parsed and verified that the specified
/// Declarator is well formed. If this is a K&R-style function, read the
/// parameters declaration-list, then start the compound-statement.
@@ -956,7 +1017,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
Diag(Tok, diag::err_expected_fn_body);
// Skip over garbage, until we get to '{'. Don't eat the '{'.
- SkipUntil(tok::l_brace, true, true);
+ SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch);
// If we didn't find the '{', bail out.
if (Tok.isNot(tok::l_brace))
@@ -979,9 +1040,10 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
// In delayed template parsing mode, for function template we consume the
// tokens and store them for late parsing at the end of the translation unit.
- if (getLangOpts().DelayedTemplateParsing &&
- Tok.isNot(tok::equal) &&
- TemplateInfo.Kind == ParsedTemplateInfo::Template) {
+ if (getLangOpts().DelayedTemplateParsing && Tok.isNot(tok::equal) &&
+ TemplateInfo.Kind == ParsedTemplateInfo::Template &&
+ !D.getDeclSpec().isConstexprSpecified() &&
+ !isFunctionDeclaratorRequiringReturnTypeDeduction(D)) {
MultiTemplateParamsArg TemplateParameterLists(*TemplateInfo.TemplateParams);
ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope);
@@ -993,22 +1055,18 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
D.complete(DP);
D.getMutableDeclSpec().abort();
- if (DP) {
- LateParsedTemplatedFunction *LPT = new LateParsedTemplatedFunction(DP);
+ CachedTokens Toks;
+ LexTemplateFunctionForLateParsing(Toks);
+ if (DP) {
FunctionDecl *FnD = 0;
if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(DP))
FnD = FunTmpl->getTemplatedDecl();
else
FnD = cast<FunctionDecl>(DP);
- Actions.CheckForFunctionRedefinition(FnD);
- LateParsedTemplateMap[FnD] = LPT;
- Actions.MarkAsLateParsedTemplate(FnD);
- LexTemplateFunctionForLateParsing(LPT->Toks);
- } else {
- CachedTokens Toks;
- LexTemplateFunctionForLateParsing(Toks);
+ Actions.CheckForFunctionRedefinition(FnD);
+ Actions.MarkAsLateParsedTemplate(FnD, DP, Toks);
}
return DP;
}
@@ -1215,7 +1273,7 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) {
if (ExpectAndConsumeSemi(diag::err_expected_semi_declaration)) {
// Skip to end of block or statement
- SkipUntil(tok::semi, true);
+ SkipUntil(tok::semi);
if (Tok.is(tok::semi))
ConsumeToken();
}
@@ -1283,7 +1341,7 @@ Parser::ExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) {
ExprResult Result(ParseAsmStringLiteral());
if (Result.isInvalid()) {
- SkipUntil(tok::r_paren, true, true);
+ SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch);
if (EndLoc)
*EndLoc = Tok.getLocation();
ConsumeAnyToken();
@@ -1422,8 +1480,9 @@ Parser::TryAnnotateName(bool IsAddressOfOperand,
return ANK_TemplateName;
}
// Fall through.
+ case Sema::NC_VarTemplate:
case Sema::NC_FunctionTemplate: {
- // We have a type or function template followed by '<'.
+ // We have a type, variable or function template followed by '<'.
ConsumeToken();
UnqualifiedId Id;
Id.setIdentifier(Name, NameLoc);
@@ -1444,6 +1503,17 @@ Parser::TryAnnotateName(bool IsAddressOfOperand,
return ANK_Unresolved;
}
+bool Parser::TryKeywordIdentFallback(bool DisableKeyword) {
+ assert(Tok.isNot(tok::identifier));
+ Diag(Tok, diag::ext_keyword_as_ident)
+ << PP.getSpelling(Tok)
+ << DisableKeyword;
+ if (DisableKeyword)
+ Tok.getIdentifierInfo()->RevertTokenIDToIdentifier();
+ Tok.setKind(tok::identifier);
+ return true;
+}
+
/// TryAnnotateTypeOrScopeToken - If the current token position is on a
/// typename (possibly qualified in C++) or a C++ scope specifier not followed
/// by a typename, TryAnnotateTypeOrScopeToken will replace one or more tokens
@@ -1473,6 +1543,23 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) {
&& "Cannot be a type or scope token!");
if (Tok.is(tok::kw_typename)) {
+ // MSVC lets you do stuff like:
+ // typename typedef T_::D D;
+ //
+ // We will consume the typedef token here and put it back after we have
+ // parsed the first identifier, transforming it into something more like:
+ // typename T_::D typedef D;
+ if (getLangOpts().MicrosoftMode && NextToken().is(tok::kw_typedef)) {
+ Token TypedefToken;
+ PP.Lex(TypedefToken);
+ bool Result = TryAnnotateTypeOrScopeToken(EnteringContext, NeedType);
+ PP.EnterToken(Tok);
+ Tok = TypedefToken;
+ if (!Result)
+ Diag(Tok.getLocation(), diag::warn_expected_qualified_after_typename);
+ return Result;
+ }
+
// Parse a C++ typename-specifier, e.g., "typename T::type".
//
// typename-specifier:
@@ -1491,7 +1578,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) {
// Attempt to recover by skipping the invalid 'typename'
if (Tok.is(tok::annot_decltype) ||
(!TryAnnotateTypeOrScopeToken(EnteringContext, NeedType) &&
- Tok.isAnnotation())) {
+ Tok.isAnnotation())) {
unsigned DiagID = diag::err_expected_qualified_after_typename;
// MS compatibility: MSVC permits using known types with typename.
// e.g. "typedef typename T* pointer_type"
@@ -1638,7 +1725,8 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(bool EnteringContext,
// annotation token to a type annotation token now.
AnnotateTemplateIdTokenAsType();
return false;
- }
+ } else if (TemplateId->Kind == TNK_Var_template)
+ return false;
}
if (SS.isEmpty())
@@ -1884,7 +1972,13 @@ Parser::DeclGroupPtrTy Parser::ParseModuleImport(SourceLocation AtLoc) {
break;
} while (true);
-
+
+ if (PP.hadModuleLoaderFatalFailure()) {
+ // With a fatal failure in the module loader, we abort parsing.
+ cutOffParsing();
+ return DeclGroupPtrTy();
+ }
+
DeclResult Import = Actions.ActOnModuleImport(AtLoc, ImportLoc, Path);
ExpectAndConsumeSemi(diag::err_module_expected_semi);
if (Import.isInvalid())
@@ -1927,11 +2021,19 @@ bool BalancedDelimiterTracker::diagnoseMissingClose() {
}
P.Diag(P.Tok, DID);
P.Diag(LOpen, diag::note_matching) << LHSName;
- if (P.SkipUntil(Close, /*StopAtSemi*/ true, /*DontConsume*/ true))
+
+ // If we're not already at some kind of closing bracket, skip to our closing
+ // token.
+ if (P.Tok.isNot(tok::r_paren) && P.Tok.isNot(tok::r_brace) &&
+ P.Tok.isNot(tok::r_square) &&
+ P.SkipUntil(Close, FinalToken,
+ Parser::StopAtSemi | Parser::StopBeforeMatch) &&
+ P.Tok.is(Close))
LClose = P.ConsumeAnyToken();
return true;
}
void BalancedDelimiterTracker::skipToEnd() {
- P.SkipUntil(Close, false);
+ P.SkipUntil(Close, Parser::StopBeforeMatch);
+ consumeClose();
}
OpenPOWER on IntegriCloud