summaryrefslogtreecommitdiff
path: root/lib/Parse/ParseTemplate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Parse/ParseTemplate.cpp')
-rw-r--r--lib/Parse/ParseTemplate.cpp77
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());
}
}