summaryrefslogtreecommitdiff
path: root/lib/Parse
diff options
context:
space:
mode:
authorRoman Divacky <rdivacky@FreeBSD.org>2009-11-18 14:59:57 +0000
committerRoman Divacky <rdivacky@FreeBSD.org>2009-11-18 14:59:57 +0000
commitb3d5a323a5ca92ea73443499cee2f15db1ff0fb3 (patch)
tree60a1694bec5a44d15456acc880cb2f91619f66aa /lib/Parse
parent8f57cb0305232cb53fff00ef151ca716766f3437 (diff)
Notes
Diffstat (limited to 'lib/Parse')
-rw-r--r--lib/Parse/AttributeList.cpp1
-rw-r--r--lib/Parse/DeclSpec.cpp10
-rw-r--r--lib/Parse/MinimalAction.cpp7
-rw-r--r--lib/Parse/ParseDecl.cpp1
-rw-r--r--lib/Parse/ParseDeclCXX.cpp17
-rw-r--r--lib/Parse/ParseExprCXX.cpp67
-rw-r--r--lib/Parse/ParseObjc.cpp51
-rw-r--r--lib/Parse/ParseTemplate.cpp163
-rw-r--r--lib/Parse/Parser.cpp1
9 files changed, 211 insertions, 107 deletions
diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp
index 344ce9e90e55..dde4bc866ac5 100644
--- a/lib/Parse/AttributeList.cpp
+++ b/lib/Parse/AttributeList.cpp
@@ -59,6 +59,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
.Case("mode", AT_mode)
.Case("used", AT_used)
.Case("alias", AT_alias)
+ .Case("cdecl", AT_cdecl)
.Case("const", AT_const)
.Case("packed", AT_packed)
.Case("malloc", AT_malloc)
diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp
index 0a4e036e4399..f00f33fcb948 100644
--- a/lib/Parse/DeclSpec.cpp
+++ b/lib/Parse/DeclSpec.cpp
@@ -13,6 +13,7 @@
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/Template.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/STLExtras.h"
@@ -26,6 +27,15 @@ static DiagnosticBuilder Diag(Diagnostic &D, SourceLocation Loc,
return D.Report(FullSourceLoc(Loc, SrcMgr), DiagID);
}
+
+void UnqualifiedId::setTemplateId(TemplateIdAnnotation *TemplateId) {
+ assert(TemplateId && "NULL template-id annotation?");
+ Kind = IK_TemplateId;
+ this->TemplateId = TemplateId;
+ StartLocation = TemplateId->TemplateNameLoc;
+ EndLocation = TemplateId->RAngleLoc;
+}
+
/// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function.
/// "TheDeclarator" is the declarator that this will be added to.
DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic,
diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp
index bf05b2baccd4..7681eac6ed8a 100644
--- a/lib/Parse/MinimalAction.cpp
+++ b/lib/Parse/MinimalAction.cpp
@@ -49,7 +49,8 @@ Action::DeclPtrTy Action::ActOnUsingDeclaration(Scope *CurScope,
const CXXScopeSpec &SS,
UnqualifiedId &Name,
AttributeList *AttrList,
- bool IsTypeName) {
+ bool IsTypeName,
+ SourceLocation TypenameLoc) {
// FIXME: Parser seems to assume that Action::ActOn* takes ownership over
// passed AttributeList, however other actions don't free it, is it
@@ -213,7 +214,9 @@ MinimalAction::ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
/// Scope will always be top level file scope.
Action::DeclPtrTy
MinimalAction::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
- IdentifierInfo **IdentList, unsigned NumElts) {
+ IdentifierInfo **IdentList,
+ SourceLocation *IdentLocs,
+ unsigned NumElts) {
for (unsigned i = 0; i != NumElts; ++i) {
// Allocate and add the 'TypeNameInfo' "decl".
getTable(TypeNameInfoTablePtr)->AddEntry(true, IdentList[i]);
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 99752b59507f..2bfda30a951b 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -14,6 +14,7 @@
#include "clang/Parse/Parser.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Scope.h"
+#include "clang/Parse/Template.h"
#include "ExtensionRAIIObject.h"
#include "llvm/ADT/SmallSet.h"
using namespace clang;
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 154c2923486e..914bfc9db89d 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -16,6 +16,7 @@
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Scope.h"
+#include "clang/Parse/Template.h"
#include "ExtensionRAIIObject.h"
using namespace clang;
@@ -282,11 +283,13 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
SourceLocation &DeclEnd,
AccessSpecifier AS) {
CXXScopeSpec SS;
+ SourceLocation TypenameLoc;
bool IsTypeName;
// Ignore optional 'typename'.
// FIXME: This is wrong; we should parse this as a typename-specifier.
if (Tok.is(tok::kw_typename)) {
+ TypenameLoc = Tok.getLocation();
ConsumeToken();
IsTypeName = true;
}
@@ -329,7 +332,7 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
tok::semi);
return Actions.ActOnUsingDeclaration(CurScope, AS, UsingLoc, SS, Name,
- AttrList, IsTypeName);
+ AttrList, IsTypeName, TypenameLoc);
}
/// ParseStaticAssertDeclaration - Parse C++0x static_assert-declaratoion.
@@ -586,13 +589,10 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// Eat the template argument list and try to continue parsing this as
// a class (or template thereof).
TemplateArgList TemplateArgs;
- TemplateArgIsTypeList TemplateArgIsType;
- TemplateArgLocationList TemplateArgLocations;
SourceLocation LAngleLoc, RAngleLoc;
if (ParseTemplateIdAfterTemplateName(TemplateTy(), NameLoc, &SS,
true, LAngleLoc,
- TemplateArgs, TemplateArgIsType,
- TemplateArgLocations, RAngleLoc)) {
+ 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();
@@ -704,7 +704,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// or explicit instantiation.
ASTTemplateArgsPtr TemplateArgsPtr(Actions,
TemplateId->getTemplateArgs(),
- TemplateId->getTemplateArgIsType(),
TemplateId->NumArgs);
if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
TUK == Action::TUK_Declaration) {
@@ -720,7 +719,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
TemplateId->TemplateNameLoc,
TemplateId->LAngleLoc,
TemplateArgsPtr,
- TemplateId->getTemplateArgLocations(),
TemplateId->RAngleLoc,
Attr);
} else if (TUK == Action::TUK_Reference) {
@@ -729,7 +727,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
TemplateId->TemplateNameLoc,
TemplateId->LAngleLoc,
TemplateArgsPtr,
- TemplateId->getTemplateArgLocations(),
TemplateId->RAngleLoc);
TypeResult = Actions.ActOnTagTemplateIdType(TypeResult, TUK,
@@ -777,7 +774,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
TemplateId->TemplateNameLoc,
TemplateId->LAngleLoc,
TemplateArgsPtr,
- TemplateId->getTemplateArgLocations(),
TemplateId->RAngleLoc,
Attr,
Action::MultiTemplateParamsArg(Actions,
@@ -1304,7 +1300,8 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
// Check for extraneous top-level semicolon.
if (Tok.is(tok::semi)) {
- Diag(Tok, diag::ext_extra_struct_semi);
+ Diag(Tok, diag::ext_extra_struct_semi)
+ << CodeModificationHint::CreateRemoval(SourceRange(Tok.getLocation()));
ConsumeToken();
continue;
}
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index a00dfb0b4c36..b2ecc9e827f1 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -14,6 +14,7 @@
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/DeclSpec.h"
+#include "clang/Parse/Template.h"
#include "llvm/Support/ErrorHandling.h"
using namespace clang;
@@ -108,52 +109,43 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
if (!HasScopeSpecifier && !ObjectType)
break;
+ TentativeParsingAction TPA(*this);
SourceLocation TemplateKWLoc = ConsumeToken();
UnqualifiedId TemplateName;
if (Tok.is(tok::identifier)) {
- TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
-
- // If the next token is not '<', we may have a stray 'template' keyword.
- // Complain and suggest removing the template keyword, but otherwise
- // allow parsing to continue.
- if (NextToken().isNot(tok::less)) {
- Diag(NextToken().getLocation(),
- diag::err_less_after_template_name_in_nested_name_spec)
- << Tok.getIdentifierInfo()->getName()
- << CodeModificationHint::CreateRemoval(SourceRange(TemplateKWLoc));
- break;
- }
-
// Consume the identifier.
+ TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
ConsumeToken();
} else if (Tok.is(tok::kw_operator)) {
if (ParseUnqualifiedIdOperator(SS, EnteringContext, ObjectType,
- TemplateName))
+ TemplateName)) {
+ TPA.Commit();
break;
+ }
if (TemplateName.getKind() != UnqualifiedId::IK_OperatorFunctionId) {
Diag(TemplateName.getSourceRange().getBegin(),
diag::err_id_after_template_in_nested_name_spec)
<< TemplateName.getSourceRange();
- break;
- } else if (Tok.isNot(tok::less)) {
- std::string OperatorName = "operator ";
- OperatorName += getOperatorSpelling(
- TemplateName.OperatorFunctionId.Operator);
- Diag(Tok.getLocation(),
- diag::err_less_after_template_name_in_nested_name_spec)
- << OperatorName
- << TemplateName.getSourceRange();
+ TPA.Commit();
break;
}
} else {
- Diag(Tok.getLocation(),
- diag::err_id_after_template_in_nested_name_spec)
- << SourceRange(TemplateKWLoc);
+ TPA.Revert();
break;
}
+ // If the next token is not '<', we have a qualified-id that refers
+ // to a template name, such as T::template apply, but is not a
+ // template-id.
+ if (Tok.isNot(tok::less)) {
+ TPA.Revert();
+ break;
+ }
+
+ // Commit to parsing the template-id.
+ TPA.Commit();
TemplateTy Template
= Actions.ActOnDependentTemplateName(TemplateKWLoc, SS, TemplateName,
ObjectType);
@@ -381,13 +373,7 @@ Parser::OwningExprResult Parser::ParseCXXCasts() {
OwningExprResult Result = ParseExpression();
// Match the ')'.
- if (Result.isInvalid())
- SkipUntil(tok::r_paren);
-
- if (Tok.is(tok::r_paren))
- RParenLoc = ConsumeParen();
- else
- MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
if (!Result.isInvalid() && !CastTy.isInvalid())
Result = Actions.ActOnCXXNamedCast(OpLoc, Kind,
@@ -820,13 +806,9 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
// Parse the enclosed template argument list.
SourceLocation LAngleLoc, RAngleLoc;
TemplateArgList TemplateArgs;
- TemplateArgIsTypeList TemplateArgIsType;
- TemplateArgLocationList TemplateArgLocations;
if (ParseTemplateIdAfterTemplateName(Template, Id.StartLocation,
&SS, true, LAngleLoc,
TemplateArgs,
- TemplateArgIsType,
- TemplateArgLocations,
RAngleLoc))
return true;
@@ -851,15 +833,10 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
TemplateId->Kind = TNK;
TemplateId->LAngleLoc = LAngleLoc;
TemplateId->RAngleLoc = RAngleLoc;
- void **Args = TemplateId->getTemplateArgs();
- bool *ArgIsType = TemplateId->getTemplateArgIsType();
- SourceLocation *ArgLocs = TemplateId->getTemplateArgLocations();
+ ParsedTemplateArgument *Args = TemplateId->getTemplateArgs();
for (unsigned Arg = 0, ArgEnd = TemplateArgs.size();
- Arg != ArgEnd; ++Arg) {
+ Arg != ArgEnd; ++Arg)
Args[Arg] = TemplateArgs[Arg];
- ArgIsType[Arg] = TemplateArgIsType[Arg];
- ArgLocs[Arg] = TemplateArgLocations[Arg];
- }
Id.setTemplateId(TemplateId);
return false;
@@ -867,14 +844,12 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
// Bundle the template arguments together.
ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateArgs.data(),
- TemplateArgIsType.data(),
TemplateArgs.size());
// Constructor and destructor names.
Action::TypeResult Type
= Actions.ActOnTemplateIdType(Template, NameLoc,
LAngleLoc, TemplateArgsPtr,
- &TemplateArgLocations[0],
RAngleLoc);
if (Type.isInvalid())
return true;
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index b043dd99f304..65bd79d6b4f2 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -61,6 +61,8 @@ Parser::DeclPtrTy Parser::ParseObjCAtDirectives() {
Parser::DeclPtrTy Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
ConsumeToken(); // the identifier "class"
llvm::SmallVector<IdentifierInfo *, 8> ClassNames;
+ llvm::SmallVector<SourceLocation, 8> ClassLocs;
+
while (1) {
if (Tok.isNot(tok::identifier)) {
@@ -69,6 +71,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
return DeclPtrTy();
}
ClassNames.push_back(Tok.getIdentifierInfo());
+ ClassLocs.push_back(Tok.getLocation());
ConsumeToken();
if (Tok.isNot(tok::comma))
@@ -81,8 +84,9 @@ Parser::DeclPtrTy Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@class"))
return DeclPtrTy();
- return Actions.ActOnForwardClassDeclaration(atLoc,
- &ClassNames[0], ClassNames.size());
+ return Actions.ActOnForwardClassDeclaration(atLoc, ClassNames.data(),
+ ClassLocs.data(),
+ ClassNames.size());
}
///
@@ -123,6 +127,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration(
Diag(Tok, diag::err_expected_ident); // missing class or category name.
return DeclPtrTy();
}
+
// We have a class or category name - consume it.
IdentifierInfo *nameId = Tok.getIdentifierInfo();
SourceLocation nameLoc = ConsumeToken();
@@ -829,6 +834,12 @@ ParseObjCProtocolReferences(llvm::SmallVectorImpl<Action::DeclPtrTy> &Protocols,
llvm::SmallVector<IdentifierLocPair, 8> ProtocolIdents;
while (1) {
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCProtocolReferences(ProtocolIdents.data(),
+ ProtocolIdents.size());
+ ConsumeToken();
+ }
+
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident);
SkipUntil(tok::greater);
@@ -895,7 +906,8 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
// Check for extraneous top-level semicolon.
if (Tok.is(tok::semi)) {
- Diag(Tok, diag::ext_extra_struct_semi);
+ Diag(Tok, diag::ext_extra_struct_semi)
+ << CodeModificationHint::CreateRemoval(SourceRange(Tok.getLocation()));
ConsumeToken();
continue;
}
@@ -982,6 +994,11 @@ Parser::DeclPtrTy Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
"ParseObjCAtProtocolDeclaration(): Expected @protocol");
ConsumeToken(); // the "protocol" identifier
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCProtocolDecl(CurScope);
+ ConsumeToken();
+ }
+
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident); // missing protocol name.
return DeclPtrTy();
@@ -1092,6 +1109,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration(
atLoc, nameId, nameLoc, categoryId,
categoryLoc);
ObjCImpDecl = ImplCatType;
+ PendingObjCImpDecl.push_back(ObjCImpDecl);
return DeclPtrTy();
}
// We have a class implementation
@@ -1114,7 +1132,8 @@ Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration(
if (Tok.is(tok::l_brace)) // we have ivars
ParseObjCClassInstanceVariables(ImplClsType/*FIXME*/, atLoc);
ObjCImpDecl = ImplClsType;
-
+ PendingObjCImpDecl.push_back(ObjCImpDecl);
+
return DeclPtrTy();
}
@@ -1126,12 +1145,21 @@ Parser::DeclPtrTy Parser::ParseObjCAtEndDeclaration(SourceLocation atLoc) {
if (ObjCImpDecl) {
Actions.ActOnAtEnd(atLoc, ObjCImpDecl);
ObjCImpDecl = DeclPtrTy();
+ PendingObjCImpDecl.pop_back();
}
else
Diag(atLoc, diag::warn_expected_implementation); // missing @implementation
return Result;
}
+Parser::DeclGroupPtrTy Parser::RetrievePendingObjCImpDecl() {
+ if (PendingObjCImpDecl.empty())
+ return Actions.ConvertDeclToDeclGroup(DeclPtrTy());
+ DeclPtrTy ImpDecl = PendingObjCImpDecl.pop_back_val();
+ Actions.ActOnAtEnd(SourceLocation(), ImpDecl);
+ return Actions.ConvertDeclToDeclGroup(ImpDecl);
+}
+
/// compatibility-alias-decl:
/// @compatibility_alias alias-name class-name ';'
///
@@ -1201,6 +1229,8 @@ Parser::DeclPtrTy Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
}
if (Tok.isNot(tok::semi))
Diag(Tok, diag::err_expected_semi_after) << "@synthesize";
+ else
+ ConsumeToken(); // consume ';'
return DeclPtrTy();
}
@@ -1406,8 +1436,10 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDefinition() {
// parse optional ';'
if (Tok.is(tok::semi)) {
- if (ObjCImpDecl)
- Diag(Tok, diag::warn_semicolon_before_method_nody);
+ if (ObjCImpDecl) {
+ Diag(Tok, diag::warn_semicolon_before_method_body)
+ << CodeModificationHint::CreateRemoval(SourceRange(Tok.getLocation()));
+ }
ConsumeToken();
}
@@ -1546,6 +1578,13 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
SourceLocation NameLoc,
IdentifierInfo *ReceiverName,
ExprArg ReceiverExpr) {
+ if (Tok.is(tok::code_completion)) {
+ if (ReceiverName)
+ Actions.CodeCompleteObjCClassMessage(CurScope, ReceiverName, NameLoc);
+ else
+ Actions.CodeCompleteObjCInstanceMessage(CurScope, ReceiverExpr.get());
+ ConsumeToken();
+ }
// Parse objc-selector
SourceLocation Loc;
IdentifierInfo *selIdent = ParseObjCSelectorPiece(Loc);
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 99578837c21c..16b1c800800f 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -15,6 +15,7 @@
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Scope.h"
+#include "clang/Parse/Template.h"
#include "llvm/Support/Compiler.h"
using namespace clang;
@@ -484,12 +485,17 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
// Get the a default value, if given.
if (Tok.is(tok::equal)) {
SourceLocation EqualLoc = ConsumeToken();
- OwningExprResult DefaultExpr = ParseCXXIdExpression();
- if (DefaultExpr.isInvalid())
+ ParsedTemplateArgument Default = ParseTemplateTemplateArgument();
+ if (Default.isInvalid()) {
+ Diag(Tok.getLocation(),
+ diag::err_default_template_template_parameter_not_template);
+ static tok::TokenKind EndToks[] = {
+ tok::comma, tok::greater, tok::greatergreater
+ };
+ SkipUntil(EndToks, 3, true, true);
return Param;
- else if (Param)
- Actions.ActOnTemplateTemplateParameterDefault(Param, EqualLoc,
- move(DefaultExpr));
+ } else if (Param)
+ Actions.ActOnTemplateTemplateParameterDefault(Param, EqualLoc, Default);
}
return Param;
@@ -582,8 +588,6 @@ Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template,
bool ConsumeLastToken,
SourceLocation &LAngleLoc,
TemplateArgList &TemplateArgs,
- TemplateArgIsTypeList &TemplateArgIsType,
- TemplateArgLocationList &TemplateArgLocations,
SourceLocation &RAngleLoc) {
assert(Tok.is(tok::less) && "Must have already parsed the template-name");
@@ -595,8 +599,7 @@ Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template,
{
GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
if (Tok.isNot(tok::greater))
- Invalid = ParseTemplateArgumentList(TemplateArgs, TemplateArgIsType,
- TemplateArgLocations);
+ Invalid = ParseTemplateArgumentList(TemplateArgs);
if (Invalid) {
// Try to find the closing '>'.
@@ -688,14 +691,10 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
// Parse the enclosed template argument list.
SourceLocation LAngleLoc, RAngleLoc;
TemplateArgList TemplateArgs;
- TemplateArgIsTypeList TemplateArgIsType;
- TemplateArgLocationList TemplateArgLocations;
bool Invalid = ParseTemplateIdAfterTemplateName(Template,
TemplateNameLoc,
SS, false, LAngleLoc,
TemplateArgs,
- TemplateArgIsType,
- TemplateArgLocations,
RAngleLoc);
if (Invalid) {
@@ -707,7 +706,6 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
}
ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateArgs.data(),
- TemplateArgIsType.data(),
TemplateArgs.size());
// Build the annotation token.
@@ -715,7 +713,6 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
Action::TypeResult Type
= Actions.ActOnTemplateIdType(Template, TemplateNameLoc,
LAngleLoc, TemplateArgsPtr,
- &TemplateArgLocations[0],
RAngleLoc);
if (Type.isInvalid()) {
// If we failed to parse the template ID but skipped ahead to a >, we're not
@@ -751,14 +748,9 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
TemplateId->Kind = TNK;
TemplateId->LAngleLoc = LAngleLoc;
TemplateId->RAngleLoc = RAngleLoc;
- void **Args = TemplateId->getTemplateArgs();
- bool *ArgIsType = TemplateId->getTemplateArgIsType();
- SourceLocation *ArgLocs = TemplateId->getTemplateArgLocations();
- for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg) {
+ ParsedTemplateArgument *Args = TemplateId->getTemplateArgs();
+ for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg)
Args[Arg] = TemplateArgs[Arg];
- ArgIsType[Arg] = TemplateArgIsType[Arg];
- ArgLocs[Arg] = TemplateArgLocations[Arg];
- }
Tok.setAnnotationValue(TemplateId);
if (TemplateKWLoc.isValid())
Tok.setLocation(TemplateKWLoc);
@@ -794,7 +786,6 @@ void Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) {
ASTTemplateArgsPtr TemplateArgsPtr(Actions,
TemplateId->getTemplateArgs(),
- TemplateId->getTemplateArgIsType(),
TemplateId->NumArgs);
Action::TypeResult Type
@@ -802,7 +793,6 @@ void Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) {
TemplateId->TemplateNameLoc,
TemplateId->LAngleLoc,
TemplateArgsPtr,
- TemplateId->getTemplateArgLocations(),
TemplateId->RAngleLoc);
// Create the new "type" annotation token.
Tok.setKind(tok::annot_typename);
@@ -817,33 +807,125 @@ void Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) {
TemplateId->Destroy();
}
+/// \brief Determine whether the given token can end a template argument.
+static bool isEndOfTemplateArgument(Token Tok) {
+ return Tok.is(tok::comma) || Tok.is(tok::greater) ||
+ Tok.is(tok::greatergreater);
+}
+
+/// \brief Parse a C++ template template argument.
+ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
+ if (!Tok.is(tok::identifier) && !Tok.is(tok::coloncolon) &&
+ !Tok.is(tok::annot_cxxscope))
+ return ParsedTemplateArgument();
+
+ // C++0x [temp.arg.template]p1:
+ // A template-argument for a template template-parameter shall be the name
+ // of a class template or a template alias, expressed as id-expression.
+ //
+ // We parse an id-expression that refers to a class template or template
+ // alias. The grammar we parse is:
+ //
+ // nested-name-specifier[opt] template[opt] identifier
+ //
+ // followed by a token that terminates a template argument, such as ',',
+ // '>', or (in some cases) '>>'.
+ CXXScopeSpec SS; // nested-name-specifier, if present
+ ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0,
+ /*EnteringContext=*/false);
+
+ if (SS.isSet() && Tok.is(tok::kw_template)) {
+ // Parse the optional 'template' keyword following the
+ // nested-name-specifier.
+ SourceLocation TemplateLoc = ConsumeToken();
+
+ if (Tok.is(tok::identifier)) {
+ // We appear to have a dependent template name.
+ UnqualifiedId Name;
+ Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
+ ConsumeToken(); // the identifier
+
+ // If the next token signals the end of a template argument,
+ // then we have a dependent template name that could be a template
+ // template argument.
+ if (isEndOfTemplateArgument(Tok)) {
+ TemplateTy Template
+ = Actions.ActOnDependentTemplateName(TemplateLoc, SS, Name,
+ /*ObjectType=*/0);
+ if (Template.get())
+ return ParsedTemplateArgument(SS, Template, Name.StartLocation);
+ }
+ }
+ } else if (Tok.is(tok::identifier)) {
+ // We may have a (non-dependent) template name.
+ TemplateTy Template;
+ UnqualifiedId Name;
+ Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
+ ConsumeToken(); // the identifier
+
+ if (isEndOfTemplateArgument(Tok)) {
+ TemplateNameKind TNK = Actions.isTemplateName(CurScope, SS, Name,
+ /*ObjectType=*/0,
+ /*EnteringContext=*/false,
+ Template);
+ if (TNK == TNK_Dependent_template_name || TNK == TNK_Type_template) {
+ // We have an id-expression that refers to a class template or
+ // (C++0x) template alias.
+ return ParsedTemplateArgument(SS, Template, Name.StartLocation);
+ }
+ }
+ }
+
+ // We don't have a template template argument.
+ return ParsedTemplateArgument();
+}
+
/// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]).
///
/// template-argument: [C++ 14.2]
/// constant-expression
/// type-id
/// id-expression
-void *Parser::ParseTemplateArgument(bool &ArgIsType) {
+ParsedTemplateArgument Parser::ParseTemplateArgument() {
// C++ [temp.arg]p2:
// In a template-argument, an ambiguity between a type-id and an
// expression is resolved to a type-id, regardless of the form of
// the corresponding template-parameter.
//
- // Therefore, we initially try to parse a type-id.
+ // Therefore, we initially try to parse a type-id.
if (isCXXTypeId(TypeIdAsTemplateArgument)) {
- ArgIsType = true;
+ SourceLocation Loc = Tok.getLocation();
TypeResult TypeArg = ParseTypeName();
if (TypeArg.isInvalid())
- return 0;
- return TypeArg.get();
+ return ParsedTemplateArgument();
+
+ return ParsedTemplateArgument(ParsedTemplateArgument::Type, TypeArg.get(),
+ Loc);
}
+
+ // Try to parse a template template argument.
+ {
+ TentativeParsingAction TPA(*this);
+ ParsedTemplateArgument TemplateTemplateArgument
+ = ParseTemplateTemplateArgument();
+ if (!TemplateTemplateArgument.isInvalid()) {
+ TPA.Commit();
+ return TemplateTemplateArgument;
+ }
+
+ // Revert this tentative parse to parse a non-type template argument.
+ TPA.Revert();
+ }
+
+ // Parse a non-type template argument.
+ SourceLocation Loc = Tok.getLocation();
OwningExprResult ExprArg = ParseConstantExpression();
if (ExprArg.isInvalid() || !ExprArg.get())
- return 0;
+ return ParsedTemplateArgument();
- ArgIsType = false;
- return ExprArg.release();
+ return ParsedTemplateArgument(ParsedTemplateArgument::NonType,
+ ExprArg.release(), Loc);
}
/// ParseTemplateArgumentList - Parse a C++ template-argument-list
@@ -853,22 +935,17 @@ void *Parser::ParseTemplateArgument(bool &ArgIsType) {
/// template-argument
/// template-argument-list ',' template-argument
bool
-Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs,
- TemplateArgIsTypeList &TemplateArgIsType,
- TemplateArgLocationList &TemplateArgLocations) {
+Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
while (true) {
- bool IsType = false;
- SourceLocation Loc = Tok.getLocation();
- void *Arg = ParseTemplateArgument(IsType);
- if (Arg) {
- TemplateArgs.push_back(Arg);
- TemplateArgIsType.push_back(IsType);
- TemplateArgLocations.push_back(Loc);
- } else {
+ ParsedTemplateArgument Arg = ParseTemplateArgument();
+ if (Arg.isInvalid()) {
SkipUntil(tok::comma, tok::greater, true, true);
return true;
}
+ // Save this template argument.
+ TemplateArgs.push_back(Arg);
+
// If the next token is a comma, consume it and keep reading
// arguments.
if (Tok.isNot(tok::comma)) break;
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 335a6cf36254..a9152745b3f7 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -15,6 +15,7 @@
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Scope.h"
+#include "clang/Parse/Template.h"
#include "llvm/Support/raw_ostream.h"
#include "ExtensionRAIIObject.h"
#include "ParsePragma.h"