diff options
Diffstat (limited to 'lib/Parse/ParseTemplate.cpp')
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 77 |
1 files changed, 49 insertions, 28 deletions
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index 063f7ccea320a..e0a7cc6e856db 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -425,7 +425,9 @@ bool Parser::isStartOfTemplateTypeParameter() { } } - if (Tok.isNot(tok::kw_typename)) + // 'typedef' is a reasonably-common typo/thinko for 'typename', and is + // ill-formed otherwise. + if (Tok.isNot(tok::kw_typename) && Tok.isNot(tok::kw_typedef)) return false; // C++ [temp.param]p2: @@ -448,6 +450,13 @@ bool Parser::isStartOfTemplateTypeParameter() { case tok::ellipsis: return true; + case tok::kw_typename: + case tok::kw_typedef: + case tok::kw_class: + // These indicate that a comma was missed after a type parameter, not that + // we have found a non-type parameter. + return true; + default: return false; } @@ -469,26 +478,25 @@ bool Parser::isStartOfTemplateTypeParameter() { /// 'template' '<' template-parameter-list '>' 'class' identifier[opt] /// = id-expression NamedDecl *Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) { - if (isStartOfTemplateTypeParameter()) - return ParseTypeParameter(Depth, Position); - - if (Tok.is(tok::kw_template)) - return ParseTemplateTemplateParameter(Depth, Position); + if (isStartOfTemplateTypeParameter()) { + // Is there just a typo in the input code? ('typedef' instead of 'typename') + if (Tok.is(tok::kw_typedef)) { + Diag(Tok.getLocation(), diag::err_expected_template_parameter); - // Is there just a typo in the input code? ('typedef' instead of 'typename') - if (Tok.is(tok::kw_typedef)) { - Diag(Tok.getLocation(), diag::err_expected_template_parameter); - - Diag(Tok.getLocation(), diag::note_meant_to_use_typename) - << FixItHint::CreateReplacement(CharSourceRange::getCharRange( - Tok.getLocation(), Tok.getEndLoc()), - "typename"); + Diag(Tok.getLocation(), diag::note_meant_to_use_typename) + << FixItHint::CreateReplacement(CharSourceRange::getCharRange( + Tok.getLocation(), Tok.getEndLoc()), + "typename"); - Tok.setKind(tok::kw_typename); + Tok.setKind(tok::kw_typename); + } return ParseTypeParameter(Depth, Position); } + if (Tok.is(tok::kw_template)) + return ParseTemplateTemplateParameter(Depth, Position); + // If it's none of the above, then it must be a parameter declaration. // NOTE: This will pick up errors in the closure of the template parameter // list (e.g., template < ; Check here to implement >> style closures. @@ -938,7 +946,9 @@ Parser::ParseTemplateIdAfterTemplateName(bool ConsumeLastToken, bool Invalid = false; { GreaterThanIsOperatorScope G(GreaterThanIsOperator, false); - if (Tok.isNot(tok::greater) && Tok.isNot(tok::greatergreater)) + if (!Tok.isOneOf(tok::greater, tok::greatergreater, + tok::greatergreatergreater, tok::greaterequal, + tok::greatergreaterequal)) Invalid = ParseTemplateArgumentList(TemplateArgs); if (Invalid) { @@ -1371,26 +1381,37 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) { SmallVector<ParseScope*, 4> TemplateParamScopeStack; - // Get the list of DeclContexts to reenter. - SmallVector<DeclContext*, 4> DeclContextsToReenter; + // Get the list of DeclContexts to reenter. For inline methods, we only want + // to push the DeclContext of the outermost class. This matches the way the + // parser normally parses bodies of inline methods when the outermost class is + // complete. + struct ContainingDC { + ContainingDC(DeclContext *DC, bool ShouldPush) : Pair(DC, ShouldPush) {} + llvm::PointerIntPair<DeclContext *, 1, bool> Pair; + DeclContext *getDC() { return Pair.getPointer(); } + bool shouldPushDC() { return Pair.getInt(); } + }; + SmallVector<ContainingDC, 4> DeclContextsToReenter; DeclContext *DD = FunD; + DeclContext *NextContaining = Actions.getContainingDC(DD); while (DD && !DD->isTranslationUnit()) { - DeclContextsToReenter.push_back(DD); + bool ShouldPush = DD == NextContaining; + DeclContextsToReenter.push_back({DD, ShouldPush}); + if (ShouldPush) + NextContaining = Actions.getContainingDC(DD); DD = DD->getLexicalParent(); } // Reenter template scopes from outermost to innermost. - SmallVectorImpl<DeclContext *>::reverse_iterator II = - DeclContextsToReenter.rbegin(); - for (; II != DeclContextsToReenter.rend(); ++II) { - TemplateParamScopeStack.push_back(new ParseScope(this, - Scope::TemplateParamScope)); - unsigned NumParamLists = - Actions.ActOnReenterTemplateScope(getCurScope(), cast<Decl>(*II)); + for (ContainingDC CDC : reverse(DeclContextsToReenter)) { + TemplateParamScopeStack.push_back( + new ParseScope(this, Scope::TemplateParamScope)); + unsigned NumParamLists = Actions.ActOnReenterTemplateScope( + getCurScope(), cast<Decl>(CDC.getDC())); CurTemplateDepthTracker.addDepth(NumParamLists); - if (*II != FunD) { + if (CDC.shouldPushDC()) { TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope)); - Actions.PushDeclContext(Actions.getCurScope(), *II); + Actions.PushDeclContext(Actions.getCurScope(), CDC.getDC()); } } |