diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-05-16 19:47:09 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-05-16 19:47:09 +0000 |
commit | 2410013d9382b8129702fa3a3bf19a370ae7afc3 (patch) | |
tree | df038b6418b19d03437950dcee799c1483c6246a /lib/Parse | |
parent | 0a5fb09b599c1bdea3cd11168bb8f4ff4040316e (diff) |
Notes
Diffstat (limited to 'lib/Parse')
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 11 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 8 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 45 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 7 | ||||
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 16 |
5 files changed, 60 insertions, 27 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 1465d21ac5ee..4ccee74eaa90 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -2577,9 +2577,9 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, // and attempt to recover. ParsedType T; IdentifierInfo *II = Tok.getIdentifierInfo(); + bool IsTemplateName = getLangOpts().CPlusPlus && NextToken().is(tok::less); Actions.DiagnoseUnknownTypeName(II, Loc, getCurScope(), SS, T, - getLangOpts().CPlusPlus && - NextToken().is(tok::less)); + IsTemplateName); if (T) { // The action has suggested that the type T could be used. Set that as // the type in the declaration specifiers, consume the would-be type @@ -2604,6 +2604,13 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, DS.SetRangeEnd(Tok.getLocation()); ConsumeToken(); + // Eat any following template arguments. + if (IsTemplateName) { + SourceLocation LAngle, RAngle; + TemplateArgList Args; + ParseTemplateIdAfterTemplateName(true, LAngle, Args, RAngle); + } + // TODO: Could inject an invalid typedef decl in an enclosing scope to // avoid rippling error messages on subsequent uses of the same type, // could be useful if #include was forgotten. diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index ad7b319676e9..e6cf65e36cfa 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -1137,8 +1137,8 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, if (!Template) { TemplateArgList TemplateArgs; SourceLocation LAngleLoc, RAngleLoc; - ParseTemplateIdAfterTemplateName(nullptr, IdLoc, SS, true, LAngleLoc, - TemplateArgs, RAngleLoc); + ParseTemplateIdAfterTemplateName(true, LAngleLoc, TemplateArgs, + RAngleLoc); return true; } @@ -1530,8 +1530,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // a class (or template thereof). TemplateArgList TemplateArgs; SourceLocation LAngleLoc, RAngleLoc; - if (ParseTemplateIdAfterTemplateName( - nullptr, NameLoc, SS, true, LAngleLoc, TemplateArgs, RAngleLoc)) { + if (ParseTemplateIdAfterTemplateName(true, LAngleLoc, TemplateArgs, + RAngleLoc)) { // We couldn't parse the template argument list at all, so don't // try to give any location information for the list. LAngleLoc = RAngleLoc = SourceLocation(); diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 3e02e46ddc7d..727fd3500991 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -235,6 +235,30 @@ bool Parser::isNotExpressionStart() { return isKnownToBeDeclarationSpecifier(); } +/// We've parsed something that could plausibly be intended to be a template +/// name (\p LHS) followed by a '<' token, and the following code can't possibly +/// be an expression. Determine if this is likely to be a template-id and if so, +/// diagnose it. +bool Parser::diagnoseUnknownTemplateId(ExprResult LHS, SourceLocation Less) { + TentativeParsingAction TPA(*this); + // FIXME: We could look at the token sequence in a lot more detail here. + if (SkipUntil(tok::greater, tok::greatergreater, tok::greatergreatergreater, + StopAtSemi | StopBeforeMatch)) { + TPA.Commit(); + + SourceLocation Greater; + ParseGreaterThanInTemplateList(Greater, true, false); + Actions.diagnoseExprIntendedAsTemplateName(getCurScope(), LHS, + Less, Greater); + return true; + } + + // There's no matching '>' token, this probably isn't supposed to be + // interpreted as a template-id. Parse it as an (ill-formed) comparison. + TPA.Revert(); + return false; +} + static bool isFoldOperator(prec::Level Level) { return Level > prec::Unknown && Level != prec::Conditional; } @@ -276,6 +300,16 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { return LHS; } + // If a '<' token is followed by a type that can be a template argument and + // cannot be an expression, then this is ill-formed, but might be intended + // to be a template-id. + if (OpToken.is(tok::less) && Actions.mightBeIntendedToBeTemplateName(LHS) && + (isKnownToBeDeclarationSpecifier() || + Tok.isOneOf(tok::greater, tok::greatergreater, + tok::greatergreatergreater)) && + diagnoseUnknownTemplateId(LHS, OpToken.getLocation())) + return ExprError(); + // If the next token is an ellipsis, then this is a fold-expression. Leave // it alone so we can handle it in the paren expression. if (isFoldOperator(NextTokPrec) && Tok.is(tok::ellipsis)) { @@ -2989,6 +3023,11 @@ Optional<AvailabilitySpec> Parser::ParseAvailabilitySpec() { return AvailabilitySpec(ConsumeToken()); } else { // Parse the platform name. + if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteAvailabilityPlatformName(); + cutOffParsing(); + return None; + } if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_avail_query_expected_platform_name); return None; @@ -3001,12 +3040,14 @@ Optional<AvailabilitySpec> Parser::ParseAvailabilitySpec() { if (Version.empty()) return None; - StringRef Platform = PlatformIdentifier->Ident->getName(); + StringRef GivenPlatform = PlatformIdentifier->Ident->getName(); + StringRef Platform = + AvailabilityAttr::canonicalizePlatformName(GivenPlatform); if (AvailabilityAttr::getPrettyPlatformName(Platform).empty()) { Diag(PlatformIdentifier->Loc, diag::err_avail_query_unrecognized_platform_name) - << Platform; + << GivenPlatform; return None; } diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 671a815911f3..56093f685617 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -2114,11 +2114,8 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, // Parse the enclosed template argument list. SourceLocation LAngleLoc, RAngleLoc; TemplateArgList TemplateArgs; - if (Tok.is(tok::less) && - ParseTemplateIdAfterTemplateName(Template, Id.StartLocation, - SS, true, LAngleLoc, - TemplateArgs, - RAngleLoc)) + if (Tok.is(tok::less) && ParseTemplateIdAfterTemplateName( + true, LAngleLoc, TemplateArgs, RAngleLoc)) return true; if (Id.getKind() == UnqualifiedId::IK_Identifier || diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index d2b18e7c0a81..6a81e14ed496 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -886,22 +886,12 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc, /// list ('<' template-parameter-list [opt] '>') and placing the /// results into a form that can be transferred to semantic analysis. /// -/// \param Template the template declaration produced by isTemplateName -/// -/// \param TemplateNameLoc the source location of the template name -/// -/// \param SS if non-NULL, the nested-name-specifier preceding the -/// template name. -/// /// \param ConsumeLastToken if true, then we will consume the last /// token that forms the template-id. Otherwise, we will leave the /// last token in the stream (e.g., so that it can be replaced with an /// annotation token). bool -Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template, - SourceLocation TemplateNameLoc, - const CXXScopeSpec &SS, - bool ConsumeLastToken, +Parser::ParseTemplateIdAfterTemplateName(bool ConsumeLastToken, SourceLocation &LAngleLoc, TemplateArgList &TemplateArgs, SourceLocation &RAngleLoc) { @@ -983,9 +973,7 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, // Parse the enclosed template argument list. SourceLocation LAngleLoc, RAngleLoc; TemplateArgList TemplateArgs; - bool Invalid = ParseTemplateIdAfterTemplateName(Template, - TemplateNameLoc, - SS, false, LAngleLoc, + bool Invalid = ParseTemplateIdAfterTemplateName(false, LAngleLoc, TemplateArgs, RAngleLoc); |