summaryrefslogtreecommitdiffstats
path: root/lib/Parse
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Parse')
-rw-r--r--lib/Parse/AttributeList.cpp6
-rw-r--r--lib/Parse/MinimalAction.cpp4
-rw-r--r--lib/Parse/ParseDecl.cpp70
-rw-r--r--lib/Parse/ParseDeclCXX.cpp21
-rw-r--r--lib/Parse/ParseExpr.cpp33
-rw-r--r--lib/Parse/ParseExprCXX.cpp140
-rw-r--r--lib/Parse/ParseObjc.cpp58
-rw-r--r--lib/Parse/ParsePragma.cpp53
-rw-r--r--lib/Parse/ParsePragma.h9
-rw-r--r--lib/Parse/ParseStmt.cpp94
-rw-r--r--lib/Parse/ParseTemplate.cpp37
-rw-r--r--lib/Parse/ParseTentative.cpp1
-rw-r--r--lib/Parse/Parser.cpp38
13 files changed, 438 insertions, 126 deletions
diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp
index bae2a09..1ebff22 100644
--- a/lib/Parse/AttributeList.cpp
+++ b/lib/Parse/AttributeList.cpp
@@ -84,6 +84,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
.Case("fastcall", AT_fastcall)
.Case("ibaction", AT_IBAction)
.Case("iboutlet", AT_IBOutlet)
+ .Case("iboutletcollection", AT_IBOutletCollection)
.Case("noreturn", AT_noreturn)
.Case("noinline", AT_noinline)
.Case("override", AT_override)
@@ -119,5 +120,10 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
.Case("cf_returns_retained", AT_cf_returns_retained)
.Case("reqd_work_group_size", AT_reqd_wg_size)
.Case("no_instrument_function", AT_no_instrument_function)
+ .Case("thiscall", AT_thiscall)
+ .Case("__cdecl", AT_cdecl)
+ .Case("__stdcall", AT_stdcall)
+ .Case("__fastcall", AT_fastcall)
+ .Case("__thiscall", AT_thiscall)
.Default(UnknownAttribute);
}
diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp
index 5a03767..b720516 100644
--- a/lib/Parse/MinimalAction.cpp
+++ b/lib/Parse/MinimalAction.cpp
@@ -194,7 +194,9 @@ MinimalAction::isTemplateName(Scope *S,
UnqualifiedId &Name,
TypeTy *ObjectType,
bool EnteringScope,
- TemplateTy &TemplateDecl) {
+ TemplateTy &TemplateDecl,
+ bool &MemberOfUnknownSpecialization) {
+ MemberOfUnknownSpecialization = false;
return TNK_Non_template;
}
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 91050e0..3e7d4a1 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -277,8 +277,8 @@ AttributeList* Parser::ParseMicrosoftTypeAttributes(AttributeList *CurrAttr) {
// Treat these like attributes
// FIXME: Allow Sema to distinguish between these and real attributes!
while (Tok.is(tok::kw___fastcall) || Tok.is(tok::kw___stdcall) ||
- Tok.is(tok::kw___cdecl) || Tok.is(tok::kw___ptr64) ||
- Tok.is(tok::kw___w64)) {
+ Tok.is(tok::kw___thiscall) || Tok.is(tok::kw___cdecl) ||
+ Tok.is(tok::kw___ptr64) || Tok.is(tok::kw___w64)) {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
if (Tok.is(tok::kw___ptr64) || Tok.is(tok::kw___w64))
@@ -364,7 +364,8 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context,
// declaration-specifiers init-declarator-list[opt] ';'
if (Tok.is(tok::semi)) {
if (RequireSemi) ConsumeToken();
- DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+ DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, AS_none,
+ DS);
DS.complete(TheDecl);
return Actions.ConvertDeclToDeclGroup(TheDecl);
}
@@ -838,7 +839,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
CCC = Action::CCC_ObjCImplementation;
Actions.CodeCompleteOrdinaryName(CurScope, CCC);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
DS.SetRangeStart(Tok.getLocation());
@@ -1143,6 +1144,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
case tok::kw___cdecl:
case tok::kw___stdcall:
case tok::kw___fastcall:
+ case tok::kw___thiscall:
DS.AddAttributes(ParseMicrosoftTypeAttributes());
continue;
@@ -1622,6 +1624,7 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
case tok::kw___cdecl:
case tok::kw___stdcall:
case tok::kw___fastcall:
+ case tok::kw___thiscall:
DS.AddAttributes(ParseMicrosoftTypeAttributes());
return true;
@@ -1674,7 +1677,7 @@ ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) {
// If there are no declarators, this is a free-standing declaration
// specifier. Let the actions module cope with it.
if (Tok.is(tok::semi)) {
- Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+ Actions.ParsedFreeStandingDeclSpec(CurScope, AS_none, DS);
return;
}
@@ -1867,7 +1870,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
if (Tok.is(tok::code_completion)) {
// Code completion for an enum name.
Actions.CodeCompleteTag(CurScope, DeclSpec::TST_enum);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
llvm::OwningPtr<AttributeList> Attr;
@@ -1875,7 +1878,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
if (Tok.is(tok::kw___attribute))
Attr.reset(ParseGNUAttributes());
- CXXScopeSpec SS;
+ CXXScopeSpec &SS = DS.getTypeSpecScope();
if (getLang().CPlusPlus) {
if (ParseOptionalCXXScopeSpecifier(SS, 0, false))
return;
@@ -2198,6 +2201,7 @@ bool Parser::isTypeSpecifierQualifier() {
case tok::kw___cdecl:
case tok::kw___stdcall:
case tok::kw___fastcall:
+ case tok::kw___thiscall:
case tok::kw___w64:
case tok::kw___ptr64:
return true;
@@ -2304,6 +2308,7 @@ bool Parser::isDeclarationSpecifier() {
case tok::kw___cdecl:
case tok::kw___stdcall:
case tok::kw___fastcall:
+ case tok::kw___thiscall:
case tok::kw___w64:
case tok::kw___ptr64:
case tok::kw___forceinline:
@@ -2401,6 +2406,7 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, bool GNUAttributesAllowed,
case tok::kw___cdecl:
case tok::kw___stdcall:
case tok::kw___fastcall:
+ case tok::kw___thiscall:
if (GNUAttributesAllowed) {
DS.AddAttributes(ParseMicrosoftTypeAttributes());
continue;
@@ -2785,8 +2791,8 @@ void Parser::ParseParenDeclarator(Declarator &D) {
}
// Eat any Microsoft extensions.
if (Tok.is(tok::kw___cdecl) || Tok.is(tok::kw___stdcall) ||
- Tok.is(tok::kw___fastcall) || Tok.is(tok::kw___w64) ||
- Tok.is(tok::kw___ptr64)) {
+ Tok.is(tok::kw___thiscall) || Tok.is(tok::kw___fastcall) ||
+ Tok.is(tok::kw___w64) || Tok.is(tok::kw___ptr64)) {
AttrList.reset(ParseMicrosoftTypeAttributes(AttrList.take()));
}
@@ -2937,9 +2943,33 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
Diag(Tok, diag::err_argument_required_after_attribute);
delete AttrList;
}
+
// Identifier list. Note that '(' identifier-list ')' is only allowed for
- // normal declarators, not for abstract-declarators.
- return ParseFunctionDeclaratorIdentifierList(LParenLoc, D);
+ // normal declarators, not for abstract-declarators. Get the first
+ // identifier.
+ Token FirstTok = Tok;
+ ConsumeToken(); // eat the first identifier.
+
+ // Identifier lists follow a really simple grammar: the identifiers can
+ // be followed *only* by a ", moreidentifiers" or ")". However, K&R
+ // identifier lists are really rare in the brave new modern world, and it
+ // is very common for someone to typo a type in a non-k&r style list. If
+ // we are presented with something like: "void foo(intptr x, float y)",
+ // we don't want to start parsing the function declarator as though it is
+ // a K&R style declarator just because intptr is an invalid type.
+ //
+ // To handle this, we check to see if the token after the first identifier
+ // is a "," or ")". Only if so, do we parse it as an identifier list.
+ if (Tok.is(tok::comma) || Tok.is(tok::r_paren))
+ return ParseFunctionDeclaratorIdentifierList(LParenLoc,
+ FirstTok.getIdentifierInfo(),
+ FirstTok.getLocation(), D);
+
+ // If we get here, the code is invalid. Push the first identifier back
+ // into the token stream and parse the first argument as an (invalid)
+ // normal argument declarator.
+ PP.EnterToken(Tok);
+ Tok = FirstTok;
}
}
@@ -3122,13 +3152,16 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
/// ParseFunctionDeclaratorIdentifierList - While parsing a function declarator
/// we found a K&R-style identifier list instead of a type argument list. The
-/// current token is known to be the first identifier in the list.
+/// first identifier has already been consumed, and the current token is the
+/// token right after it.
///
/// identifier-list: [C99 6.7.5]
/// identifier
/// identifier-list ',' identifier
///
void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc,
+ IdentifierInfo *FirstIdent,
+ SourceLocation FirstIdentLoc,
Declarator &D) {
// Build up an array of information about the parsed arguments.
llvm::SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
@@ -3139,17 +3172,14 @@ void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc,
// to be abstract. In abstract-declarators, identifier lists are not valid:
// diagnose this.
if (!D.getIdentifier())
- Diag(Tok, diag::ext_ident_list_in_param);
+ Diag(FirstIdentLoc, diag::ext_ident_list_in_param);
- // Tok is known to be the first identifier in the list. Remember this
- // identifier in ParamInfo.
- ParamsSoFar.insert(Tok.getIdentifierInfo());
- ParamInfo.push_back(DeclaratorChunk::ParamInfo(Tok.getIdentifierInfo(),
- Tok.getLocation(),
+ // The first identifier was already read, and is known to be the first
+ // identifier in the list. Remember this identifier in ParamInfo.
+ ParamsSoFar.insert(FirstIdent);
+ ParamInfo.push_back(DeclaratorChunk::ParamInfo(FirstIdent, FirstIdentLoc,
DeclPtrTy()));
- ConsumeToken(); // eat the first identifier.
-
while (Tok.is(tok::comma)) {
// Eat the comma.
ConsumeToken();
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 015ac5b..479c04c 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -50,7 +50,7 @@ Parser::DeclPtrTy Parser::ParseNamespace(unsigned Context,
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteNamespaceDecl(CurScope);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
SourceLocation IdentLoc;
@@ -87,6 +87,14 @@ Parser::DeclPtrTy Parser::ParseNamespace(unsigned Context,
SourceLocation LBrace = ConsumeBrace();
+ if (CurScope->isClassScope() || CurScope->isTemplateParamScope() ||
+ CurScope->isInObjcMethodScope() || CurScope->getBlockParent() ||
+ CurScope->getFnParent()) {
+ Diag(LBrace, diag::err_namespace_nonnamespace_scope);
+ SkipUntil(tok::r_brace, false);
+ return DeclPtrTy();
+ }
+
// Enter a scope for the namespace.
ParseScope NamespaceScope(this, Scope::DeclScope);
@@ -128,7 +136,7 @@ Parser::DeclPtrTy Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteNamespaceAliasDecl(CurScope);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
CXXScopeSpec SS;
@@ -223,7 +231,7 @@ Parser::DeclPtrTy Parser::ParseUsingDirectiveOrDeclaration(unsigned Context,
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteUsing(CurScope);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
if (Tok.is(tok::kw_namespace))
@@ -260,7 +268,7 @@ Parser::DeclPtrTy Parser::ParseUsingDirective(unsigned Context,
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteUsingDirective(CurScope);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
CXXScopeSpec SS;
@@ -602,7 +610,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
if (Tok.is(tok::code_completion)) {
// Code completion for a struct, class, or union name.
Actions.CodeCompleteTag(CurScope, TagType);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
AttributeList *AttrList = 0;
@@ -973,6 +981,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
case tok::kw_typedef: // struct foo {...} typedef x;
case tok::kw_register: // struct foo {...} register x;
case tok::kw_auto: // struct foo {...} auto x;
+ case tok::kw_mutable: // struct foo {...} mutable x;
// As shown above, type qualifiers and storage class specifiers absolutely
// can occur after class specifiers according to the grammar. However,
// almost noone actually writes code like this. If we see one of these,
@@ -1298,7 +1307,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
if (Tok.is(tok::semi)) {
ConsumeToken();
- Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+ Actions.ParsedFreeStandingDeclSpec(CurScope, AS, DS);
return;
}
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index b9e632a..b036e56 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -222,7 +222,7 @@ Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) {
Parser::OwningExprResult Parser::ParseAssignmentExpression() {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Expression);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
if (Tok.is(tok::kw_throw))
@@ -315,8 +315,29 @@ Parser::ParseRHSOfBinaryExpression(OwningExprResult LHS, prec::Level MinPrec) {
// Eat the colon.
ColonLoc = ConsumeToken();
} else {
+ // Otherwise, we're missing a ':'. Assume that this was a typo that the
+ // user forgot. If we're not in a macro instantion, we can suggest a
+ // fixit hint. If there were two spaces before the current token,
+ // suggest inserting the colon in between them, otherwise insert ": ".
+ SourceLocation FILoc = Tok.getLocation();
+ const char *FIText = ": ";
+ if (FILoc.isFileID()) {
+ const SourceManager &SM = PP.getSourceManager();
+ bool IsInvalid = false;
+ const char *SourcePtr =
+ SM.getCharacterData(FILoc.getFileLocWithOffset(-1), &IsInvalid);
+ if (!IsInvalid && *SourcePtr == ' ') {
+ SourcePtr =
+ SM.getCharacterData(FILoc.getFileLocWithOffset(-2), &IsInvalid);
+ if (!IsInvalid && *SourcePtr == ' ') {
+ FILoc = FILoc.getFileLocWithOffset(-1);
+ FIText = ":";
+ }
+ }
+ }
+
Diag(Tok, diag::err_expected_colon)
- << FixItHint::CreateInsertion(Tok.getLocation(), ": ");
+ << FixItHint::CreateInsertion(FILoc, FIText);
Diag(OpToken, diag::note_matching) << "?";
ColonLoc = Tok.getLocation();
}
@@ -885,7 +906,7 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
return ParsePostfixExpressionSuffix(ParseBlockLiteralExpression());
case tok::code_completion:
Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Expression);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
NotCastExpr, TypeOfCast);
case tok::l_square:
@@ -954,7 +975,7 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteCall(CurScope, LHS.get(), 0, 0);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
if (Tok.isNot(tok::r_paren)) {
@@ -1008,7 +1029,7 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
Actions.CodeCompleteMemberReferenceExpr(CurScope, LHS.get(),
OpLoc, OpKind == tok::arrow);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
if (MayBePseudoDestructor) {
@@ -1541,7 +1562,7 @@ bool Parser::ParseExpressionList(ExprListTy &Exprs, CommaLocsTy &CommaLocs,
if (Tok.is(tok::code_completion)) {
if (Completer)
(Actions.*Completer)(CurScope, Data, Exprs.data(), Exprs.size());
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
OwningExprResult Expr(ParseAssignmentExpression());
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 146762b..46f1d94 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -110,7 +110,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
// Code completion for a nested-name-specifier, where the code
// code completion token follows the '::'.
Actions.CodeCompleteQualifiedId(CurScope, SS, EnteringContext);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
}
@@ -289,11 +289,13 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
TemplateTy Template;
UnqualifiedId TemplateName;
TemplateName.setIdentifier(&II, Tok.getLocation());
+ bool MemberOfUnknownSpecialization;
if (TemplateNameKind TNK = Actions.isTemplateName(CurScope, SS,
TemplateName,
ObjectType,
EnteringContext,
- Template)) {
+ Template,
+ MemberOfUnknownSpecialization)) {
// We have found a template name, so annotate this this token
// with a template-id annotation. We do not permit the
// template-id to be translated into a type annotation,
@@ -305,6 +307,31 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
SourceLocation(), false))
return true;
continue;
+ }
+
+ if (MemberOfUnknownSpecialization && (ObjectType || SS.isSet()) &&
+ IsTemplateArgumentList(1)) {
+ // We have something like t::getAs<T>, where getAs is a
+ // member of an unknown specialization. However, this will only
+ // parse correctly as a template, so suggest the keyword 'template'
+ // before 'getAs' and treat this as a dependent template name.
+ Diag(Tok.getLocation(), diag::err_missing_dependent_template_keyword)
+ << II.getName()
+ << FixItHint::CreateInsertion(Tok.getLocation(), "template ");
+
+ Template = Actions.ActOnDependentTemplateName(Tok.getLocation(), SS,
+ TemplateName, ObjectType,
+ EnteringContext);
+ if (!Template.get())
+ return true;
+
+ // Consume the identifier.
+ ConsumeToken();
+ if (AnnotateTemplateIdToken(Template, TNK_Dependent_template_name, &SS,
+ TemplateName, SourceLocation(), false))
+ return true;
+
+ continue;
}
}
@@ -576,7 +603,8 @@ Parser::ParseCXXPseudoDestructor(ExprArg Base, SourceLocation OpLoc,
// it as such.
if (Tok.is(tok::less) &&
ParseUnqualifiedIdTemplateId(SS, Name, NameLoc, false, ObjectType,
- SecondTypeName, /*AssumeTemplateName=*/true))
+ SecondTypeName, /*AssumeTemplateName=*/true,
+ /*TemplateKWLoc*/SourceLocation()))
return ExprError();
return Actions.ActOnPseudoDestructorExpr(CurScope, move(Base), OpLoc, OpKind,
@@ -688,17 +716,33 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
/// \param DeclResult if the condition was parsed as a declaration, the
/// parsed declaration.
///
+/// \param Loc The location of the start of the statement that requires this
+/// condition, e.g., the "for" in a for loop.
+///
+/// \param ConvertToBoolean Whether the condition expression should be
+/// converted to a boolean value.
+///
/// \returns true if there was a parsing, false otherwise.
bool Parser::ParseCXXCondition(OwningExprResult &ExprResult,
- DeclPtrTy &DeclResult) {
+ DeclPtrTy &DeclResult,
+ SourceLocation Loc,
+ bool ConvertToBoolean) {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Condition);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
if (!isCXXConditionDeclaration()) {
+ // Parse the expression.
ExprResult = ParseExpression(); // expression
DeclResult = DeclPtrTy();
+ if (ExprResult.isInvalid())
+ return true;
+
+ // If required, convert to a boolean value.
+ if (ConvertToBoolean)
+ ExprResult
+ = Actions.ActOnBooleanCondition(CurScope, Loc, move(ExprResult));
return ExprResult.isInvalid();
}
@@ -746,6 +790,9 @@ bool Parser::ParseCXXCondition(OwningExprResult &ExprResult,
Diag(Tok, diag::err_expected_equal_after_declarator);
}
+ // FIXME: Build a reference to this declaration? Convert it to bool?
+ // (This is currently handled by Sema).
+
return false;
}
@@ -952,8 +999,10 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
bool EnteringContext,
TypeTy *ObjectType,
UnqualifiedId &Id,
- bool AssumeTemplateId) {
- assert(Tok.is(tok::less) && "Expected '<' to finish parsing a template-id");
+ bool AssumeTemplateId,
+ SourceLocation TemplateKWLoc) {
+ assert((AssumeTemplateId || Tok.is(tok::less)) &&
+ "Expected '<' to finish parsing a template-id");
TemplateTy Template;
TemplateNameKind TNK = TNK_Non_template;
@@ -962,30 +1011,63 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
case UnqualifiedId::IK_OperatorFunctionId:
case UnqualifiedId::IK_LiteralOperatorId:
if (AssumeTemplateId) {
- Template = Actions.ActOnDependentTemplateName(SourceLocation(), SS,
+ Template = Actions.ActOnDependentTemplateName(TemplateKWLoc, SS,
Id, ObjectType,
EnteringContext);
TNK = TNK_Dependent_template_name;
if (!Template.get())
return true;
- } else
+ } else {
+ bool MemberOfUnknownSpecialization;
TNK = Actions.isTemplateName(CurScope, SS, Id, ObjectType,
- EnteringContext, Template);
+ EnteringContext, Template,
+ MemberOfUnknownSpecialization);
+
+ if (TNK == TNK_Non_template && MemberOfUnknownSpecialization &&
+ ObjectType && IsTemplateArgumentList()) {
+ // We have something like t->getAs<T>(), where getAs is a
+ // member of an unknown specialization. However, this will only
+ // parse correctly as a template, so suggest the keyword 'template'
+ // before 'getAs' and treat this as a dependent template name.
+ std::string Name;
+ if (Id.getKind() == UnqualifiedId::IK_Identifier)
+ Name = Id.Identifier->getName();
+ else {
+ Name = "operator ";
+ if (Id.getKind() == UnqualifiedId::IK_OperatorFunctionId)
+ Name += getOperatorSpelling(Id.OperatorFunctionId.Operator);
+ else
+ Name += Id.Identifier->getName();
+ }
+ Diag(Id.StartLocation, diag::err_missing_dependent_template_keyword)
+ << Name
+ << FixItHint::CreateInsertion(Id.StartLocation, "template ");
+ Template = Actions.ActOnDependentTemplateName(TemplateKWLoc, SS,
+ Id, ObjectType,
+ EnteringContext);
+ TNK = TNK_Dependent_template_name;
+ if (!Template.get())
+ return true;
+ }
+ }
break;
case UnqualifiedId::IK_ConstructorName: {
UnqualifiedId TemplateName;
+ bool MemberOfUnknownSpecialization;
TemplateName.setIdentifier(Name, NameLoc);
TNK = Actions.isTemplateName(CurScope, SS, TemplateName, ObjectType,
- EnteringContext, Template);
+ EnteringContext, Template,
+ MemberOfUnknownSpecialization);
break;
}
case UnqualifiedId::IK_DestructorName: {
UnqualifiedId TemplateName;
+ bool MemberOfUnknownSpecialization;
TemplateName.setIdentifier(Name, NameLoc);
if (ObjectType) {
- Template = Actions.ActOnDependentTemplateName(SourceLocation(), SS,
+ Template = Actions.ActOnDependentTemplateName(TemplateKWLoc, SS,
TemplateName, ObjectType,
EnteringContext);
TNK = TNK_Dependent_template_name;
@@ -993,7 +1075,8 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
return true;
} else {
TNK = Actions.isTemplateName(CurScope, SS, TemplateName, ObjectType,
- EnteringContext, Template);
+ EnteringContext, Template,
+ MemberOfUnknownSpecialization);
if (TNK == TNK_Non_template && Id.DestructorName == 0) {
Diag(NameLoc, diag::err_destructor_template_id)
@@ -1014,7 +1097,8 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
// Parse the enclosed template argument list.
SourceLocation LAngleLoc, RAngleLoc;
TemplateArgList TemplateArgs;
- if (ParseTemplateIdAfterTemplateName(Template, Id.StartLocation,
+ if (Tok.is(tok::less) &&
+ ParseTemplateIdAfterTemplateName(Template, Id.StartLocation,
&SS, true, LAngleLoc,
TemplateArgs,
RAngleLoc))
@@ -1190,7 +1274,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
Actions.CodeCompleteOperatorName(CurScope);
// Consume the operator token.
- ConsumeToken();
+ ConsumeCodeCompletionToken();
// Don't try to parse any further.
return true;
@@ -1293,6 +1377,17 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
bool AllowConstructorName,
TypeTy *ObjectType,
UnqualifiedId &Result) {
+
+ // Handle 'A::template B'. This is for template-ids which have not
+ // already been annotated by ParseOptionalCXXScopeSpecifier().
+ bool TemplateSpecified = false;
+ SourceLocation TemplateKWLoc;
+ if (getLang().CPlusPlus && Tok.is(tok::kw_template) &&
+ (ObjectType || SS.isSet())) {
+ TemplateSpecified = true;
+ TemplateKWLoc = ConsumeToken();
+ }
+
// unqualified-id:
// identifier
// template-id (when it hasn't already been annotated)
@@ -1320,9 +1415,10 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
}
// If the next token is a '<', we may have a template.
- if (Tok.is(tok::less))
+ if (TemplateSpecified || Tok.is(tok::less))
return ParseUnqualifiedIdTemplateId(SS, Id, IdLoc, EnteringContext,
- ObjectType, Result);
+ ObjectType, Result,
+ TemplateSpecified, TemplateKWLoc);
return false;
}
@@ -1383,10 +1479,11 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
// operator-function-id < template-argument-list[opt] >
if ((Result.getKind() == UnqualifiedId::IK_OperatorFunctionId ||
Result.getKind() == UnqualifiedId::IK_LiteralOperatorId) &&
- Tok.is(tok::less))
+ (TemplateSpecified || Tok.is(tok::less)))
return ParseUnqualifiedIdTemplateId(SS, 0, SourceLocation(),
EnteringContext, ObjectType,
- Result);
+ Result,
+ TemplateSpecified, TemplateKWLoc);
return false;
}
@@ -1411,10 +1508,11 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
IdentifierInfo *ClassName = Tok.getIdentifierInfo();
SourceLocation ClassNameLoc = ConsumeToken();
- if (Tok.is(tok::less)) {
+ if (TemplateSpecified || Tok.is(tok::less)) {
Result.setDestructorName(TildeLoc, 0, ClassNameLoc);
return ParseUnqualifiedIdTemplateId(SS, ClassName, ClassNameLoc,
- EnteringContext, ObjectType, Result);
+ EnteringContext, ObjectType, Result,
+ TemplateSpecified, TemplateKWLoc);
}
// Note that this is a destructor name.
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index 7b1ecf6..9cfe734 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -32,7 +32,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtDirectives() {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCAtDirective(CurScope, ObjCImpDecl, false);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
switch (Tok.getObjCKeywordID()) {
@@ -131,7 +131,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration(
// Code completion after '@interface'.
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCInterfaceDecl(CurScope);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
if (Tok.isNot(tok::identifier)) {
@@ -149,7 +149,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration(
IdentifierInfo *categoryId = 0;
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCInterfaceCategory(CurScope, nameId, nameLoc);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
// For ObjC2, the category name is optional (not an error).
@@ -204,7 +204,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration(
// Code completion of superclass names.
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCSuperclass(CurScope, nameId, nameLoc);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
if (Tok.isNot(tok::identifier)) {
@@ -350,7 +350,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
Actions.CodeCompleteOrdinaryName(CurScope,
ObjCImpDecl? Action::CCC_ObjCImplementation
: Action::CCC_ObjCInterface);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
// If we don't have an @ directive, parse it as a function definition.
@@ -371,7 +371,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
SourceLocation AtLoc = ConsumeToken(); // the "@"
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCAtDirective(CurScope, ObjCImpDecl, true);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
break;
}
@@ -438,7 +438,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
// EOF. In the former case, eat the @end. In the later case, emit an error.
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCAtDirective(CurScope, ObjCImpDecl, true);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
} else if (Tok.isObjCAtKeyword(tok::objc_end))
ConsumeToken(); // the "end" identifier
else
@@ -446,7 +446,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
// Insert collected methods declarations into the @interface object.
// This passes in an invalid SourceLocation for AtEndLoc when EOF is hit.
- Actions.ActOnAtEnd(AtEnd, interfaceDecl,
+ Actions.ActOnAtEnd(CurScope, AtEnd, interfaceDecl,
allMethods.data(), allMethods.size(),
allProperties.data(), allProperties.size(),
allTUVariables.data(), allTUVariables.size());
@@ -477,7 +477,7 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS, DeclPtrTy ClassDecl,
while (1) {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCPropertyFlags(CurScope, DS);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
const IdentifierInfo *II = Tok.getIdentifierInfo();
@@ -514,7 +514,7 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS, DeclPtrTy ClassDecl,
else
Actions.CodeCompleteObjCPropertyGetter(CurScope, ClassDecl,
Methods, NumMethods);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
if (Tok.isNot(tok::identifier)) {
@@ -782,7 +782,7 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCMethodDecl(CurScope, mType == tok::minus,
/*ReturnType=*/0, IDecl);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
// Parse the return type if present.
@@ -799,7 +799,7 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCMethodDecl(CurScope, mType == tok::minus,
ReturnType, IDecl);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
// Now parse the selector.
@@ -945,7 +945,7 @@ ParseObjCProtocolReferences(llvm::SmallVectorImpl<Action::DeclPtrTy> &Protocols,
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCProtocolReferences(ProtocolIdents.data(),
ProtocolIdents.size());
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
if (Tok.isNot(tok::identifier)) {
@@ -1026,7 +1026,7 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCAtVisibility(CurScope);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
switch (Tok.getObjCKeywordID()) {
@@ -1046,7 +1046,7 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteOrdinaryName(CurScope,
Action::CCC_ObjCInstanceVariableList);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
struct ObjCIvarCallback : FieldCallback {
@@ -1117,7 +1117,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCProtocolDecl(CurScope);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
if (Tok.isNot(tok::identifier)) {
@@ -1203,7 +1203,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration(
// Code completion after '@implementation'.
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCImplementationDecl(CurScope);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
if (Tok.isNot(tok::identifier)) {
@@ -1222,7 +1222,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration(
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCImplementationCategory(CurScope, nameId, nameLoc);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
if (Tok.is(tok::identifier)) {
@@ -1277,7 +1277,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) {
DeclPtrTy Result = ObjCImpDecl;
ConsumeToken(); // the "end" identifier
if (ObjCImpDecl) {
- Actions.ActOnAtEnd(atEnd, ObjCImpDecl);
+ Actions.ActOnAtEnd(CurScope, atEnd, ObjCImpDecl);
ObjCImpDecl = DeclPtrTy();
PendingObjCImpDecl.pop_back();
}
@@ -1292,7 +1292,7 @@ Parser::DeclGroupPtrTy Parser::RetrievePendingObjCImpDecl() {
if (PendingObjCImpDecl.empty())
return Actions.ConvertDeclToDeclGroup(DeclPtrTy());
DeclPtrTy ImpDecl = PendingObjCImpDecl.pop_back_val();
- Actions.ActOnAtEnd(SourceRange(), ImpDecl);
+ Actions.ActOnAtEnd(CurScope, SourceRange(), ImpDecl);
return Actions.ConvertDeclToDeclGroup(ImpDecl);
}
@@ -1342,7 +1342,7 @@ Parser::DeclPtrTy Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
while (true) {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCPropertyDefinition(CurScope, ObjCImpDecl);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
if (Tok.isNot(tok::identifier)) {
@@ -1361,7 +1361,7 @@ Parser::DeclPtrTy Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCPropertySynthesizeIvar(CurScope, propertyId,
ObjCImpDecl);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
if (Tok.isNot(tok::identifier)) {
@@ -1371,7 +1371,7 @@ Parser::DeclPtrTy Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
propertyIvar = Tok.getIdentifierInfo();
ConsumeToken(); // consume ivar-name
}
- Actions.ActOnPropertyImplDecl(atLoc, propertyLoc, true, ObjCImpDecl,
+ Actions.ActOnPropertyImplDecl(CurScope, atLoc, propertyLoc, true, ObjCImpDecl,
propertyId, propertyIvar);
if (Tok.isNot(tok::comma))
break;
@@ -1400,7 +1400,7 @@ Parser::DeclPtrTy Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
while (true) {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCPropertyDefinition(CurScope, ObjCImpDecl);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
if (Tok.isNot(tok::identifier)) {
@@ -1411,7 +1411,7 @@ Parser::DeclPtrTy Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
IdentifierInfo *propertyId = Tok.getIdentifierInfo();
SourceLocation propertyLoc = ConsumeToken(); // consume property name
- Actions.ActOnPropertyImplDecl(atLoc, propertyLoc, false, ObjCImpDecl,
+ Actions.ActOnPropertyImplDecl(CurScope, atLoc, propertyLoc, false, ObjCImpDecl,
propertyId, 0);
if (Tok.isNot(tok::comma))
@@ -1654,7 +1654,7 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDefinition() {
Parser::OwningStmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCAtStatement(CurScope);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
return StmtError();
}
@@ -1685,7 +1685,7 @@ Parser::OwningExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
switch (Tok.getKind()) {
case tok::code_completion:
Actions.CodeCompleteObjCAtExpression(CurScope);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
return ExprError();
case tok::string_literal: // primary-expression: string-literal
@@ -1925,7 +1925,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
else
Actions.CodeCompleteObjCInstanceMessage(CurScope, ReceiverExpr.get(),
0, 0);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
// Parse objc-selector
@@ -1979,7 +1979,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
Actions.CodeCompleteObjCInstanceMessage(CurScope, ReceiverExpr.get(),
KeyIdents.data(),
KeyIdents.size());
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
// Check for another keyword selector.
diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp
index 812d8e2..c4e4a52 100644
--- a/lib/Parse/ParsePragma.cpp
+++ b/lib/Parse/ParsePragma.cpp
@@ -23,7 +23,6 @@ using namespace clang;
// pack '(' 'show' ')'
// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) {
- // FIXME: Should we be expanding macros here? My guess is no.
SourceLocation PackLoc = PackTok.getLocation();
Token Tok;
@@ -100,17 +99,67 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) {
return;
}
+ SourceLocation RParenLoc = Tok.getLocation();
PP.Lex(Tok);
if (Tok.isNot(tok::eom)) {
PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
return;
}
- SourceLocation RParenLoc = Tok.getLocation();
Actions.ActOnPragmaPack(Kind, Name, Alignment.release(), PackLoc,
LParenLoc, RParenLoc);
}
+// #pragma 'options' 'align' '=' {'natural', 'mac68k', 'power', 'reset'}
+void PragmaOptionsHandler::HandlePragma(Preprocessor &PP, Token &OptionsTok) {
+ SourceLocation OptionsLoc = OptionsTok.getLocation();
+
+ Token Tok;
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::identifier) || !Tok.getIdentifierInfo()->isStr("align")) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
+ return;
+ }
+
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::equal)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_equal);
+ return;
+ }
+
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::identifier)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
+ << "options";
+ return;
+ }
+
+ Action::PragmaOptionsAlignKind Kind = Action::POAK_Natural;
+ const IdentifierInfo *II = Tok.getIdentifierInfo();
+ if (II->isStr("natural"))
+ Kind = Action::POAK_Natural;
+ else if (II->isStr("power"))
+ Kind = Action::POAK_Power;
+ else if (II->isStr("mac68k"))
+ Kind = Action::POAK_Mac68k;
+ else if (II->isStr("reset"))
+ Kind = Action::POAK_Reset;
+ else {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_options_invalid_option);
+ return;
+ }
+
+ SourceLocation KindLoc = Tok.getLocation();
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::eom)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
+ << "options";
+ return;
+ }
+
+ Actions.ActOnPragmaOptionsAlign(Kind, OptionsLoc, KindLoc);
+}
+
// #pragma unused(identifier)
void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, Token &UnusedTok) {
// FIXME: Should we be expanding macros here? My guess is no.
diff --git a/lib/Parse/ParsePragma.h b/lib/Parse/ParsePragma.h
index db385c6..d9d06a1 100644
--- a/lib/Parse/ParsePragma.h
+++ b/lib/Parse/ParsePragma.h
@@ -20,6 +20,15 @@ namespace clang {
class Action;
class Parser;
+class PragmaOptionsHandler : public PragmaHandler {
+ Action &Actions;
+public:
+ PragmaOptionsHandler(const IdentifierInfo *N, Action &A) : PragmaHandler(N),
+ Actions(A) {}
+
+ virtual void HandlePragma(Preprocessor &PP, Token &FirstToken);
+};
+
class PragmaPackHandler : public PragmaHandler {
Action &Actions;
public:
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index 9b22270..98c0058 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -283,7 +283,7 @@ Parser::OwningStmtResult Parser::ParseCaseStatement(AttributeList *Attr) {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteCase(CurScope);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
/// We don't want to treat 'case x : y' as a potential typo for 'case x::y'.
@@ -536,15 +536,23 @@ Parser::OwningStmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
/// successfully parsed. Note that a successful parse can still have semantic
/// errors in the condition.
bool Parser::ParseParenExprOrCondition(OwningExprResult &ExprResult,
- DeclPtrTy &DeclResult) {
+ DeclPtrTy &DeclResult,
+ SourceLocation Loc,
+ bool ConvertToBoolean) {
bool ParseError = false;
SourceLocation LParenLoc = ConsumeParen();
if (getLang().CPlusPlus)
- ParseError = ParseCXXCondition(ExprResult, DeclResult);
+ ParseError = ParseCXXCondition(ExprResult, DeclResult, Loc,
+ ConvertToBoolean);
else {
ExprResult = ParseExpression();
DeclResult = DeclPtrTy();
+
+ // If required, convert to a boolean value.
+ if (!ExprResult.isInvalid() && ConvertToBoolean)
+ ExprResult
+ = Actions.ActOnBooleanCondition(CurScope, Loc, move(ExprResult));
}
// If the parser was confused by the condition and we don't have a ')', try to
@@ -603,7 +611,7 @@ Parser::OwningStmtResult Parser::ParseIfStatement(AttributeList *Attr) {
// Parse the condition.
OwningExprResult CondExp(Actions);
DeclPtrTy CondVar;
- if (ParseParenExprOrCondition(CondExp, CondVar))
+ if (ParseParenExprOrCondition(CondExp, CondVar, IfLoc, true))
return StmtError();
FullExprArg FullCondExp(Actions.MakeFullExpr(CondExp));
@@ -735,13 +743,25 @@ Parser::OwningStmtResult Parser::ParseSwitchStatement(AttributeList *Attr) {
// Parse the condition.
OwningExprResult Cond(Actions);
DeclPtrTy CondVar;
- if (ParseParenExprOrCondition(Cond, CondVar))
+ if (ParseParenExprOrCondition(Cond, CondVar, SwitchLoc, false))
return StmtError();
- FullExprArg FullCond(Actions.MakeFullExpr(Cond));
+ OwningStmtResult Switch
+ = Actions.ActOnStartOfSwitchStmt(SwitchLoc, move(Cond), CondVar);
+
+ if (Switch.isInvalid()) {
+ // Skip the switch body.
+ // FIXME: This is not optimal recovery, but parsing the body is more
+ // dangerous due to the presence of case and default statements, which
+ // will have no place to connect back with the switch.
+ if (Tok.is(tok::l_brace)) {
+ ConsumeBrace();
+ SkipUntil(tok::r_brace, false, false);
+ } else
+ SkipUntil(tok::semi);
+ return move(Switch);
+ }
- OwningStmtResult Switch = Actions.ActOnStartOfSwitchStmt(FullCond, CondVar);
-
// C99 6.8.4p3 - In C99, the body of the switch statement is a scope, even if
// there is no compound stmt. C90 does not have this clause. We only do this
// if the body isn't a compound statement to avoid push/pop in common cases.
@@ -763,11 +783,6 @@ Parser::OwningStmtResult Parser::ParseSwitchStatement(AttributeList *Attr) {
InnerScope.Exit();
SwitchScope.Exit();
- if (Cond.isInvalid() && !CondVar.get()) {
- Actions.ActOnSwitchBodyError(SwitchLoc, move(Switch), move(Body));
- return StmtError();
- }
-
if (Body.isInvalid())
// FIXME: Remove the case statement list from the Switch statement.
Body = Actions.ActOnNullStmt(Tok.getLocation());
@@ -818,7 +833,7 @@ Parser::OwningStmtResult Parser::ParseWhileStatement(AttributeList *Attr) {
// Parse the condition.
OwningExprResult Cond(Actions);
DeclPtrTy CondVar;
- if (ParseParenExprOrCondition(Cond, CondVar))
+ if (ParseParenExprOrCondition(Cond, CondVar, WhileLoc, true))
return StmtError();
FullExprArg FullCond(Actions.MakeFullExpr(Cond));
@@ -975,14 +990,17 @@ Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) {
bool ForEach = false;
OwningStmtResult FirstPart(Actions);
- OwningExprResult SecondPart(Actions), ThirdPart(Actions);
+ bool SecondPartIsInvalid = false;
+ FullExprArg SecondPart(Actions);
+ OwningExprResult Collection(Actions);
+ FullExprArg ThirdPart(Actions);
DeclPtrTy SecondVar;
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteOrdinaryName(CurScope,
C99orCXXorObjC? Action::CCC_ForInit
: Action::CCC_Expression);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
// Parse the first part of the for specifier.
@@ -1009,7 +1027,7 @@ Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) {
Actions.ActOnForEachDeclStmt(DG);
// ObjC: for (id x in expr)
ConsumeToken(); // consume 'in'
- SecondPart = ParseExpression();
+ Collection = ParseExpression();
} else {
Diag(Tok, diag::err_expected_semi_for);
SkipUntil(tok::semi);
@@ -1025,35 +1043,44 @@ Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) {
ConsumeToken();
} else if ((ForEach = isTokIdentifier_in())) {
ConsumeToken(); // consume 'in'
- SecondPart = ParseExpression();
+ Collection = ParseExpression();
} else {
if (!Value.isInvalid()) Diag(Tok, diag::err_expected_semi_for);
SkipUntil(tok::semi);
}
}
if (!ForEach) {
- assert(!SecondPart.get() && "Shouldn't have a second expression yet.");
+ assert(!SecondPart->get() && "Shouldn't have a second expression yet.");
// Parse the second part of the for specifier.
if (Tok.is(tok::semi)) { // for (...;;
// no second part.
} else {
+ OwningExprResult Second(Actions);
if (getLang().CPlusPlus)
- ParseCXXCondition(SecondPart, SecondVar);
- else
- SecondPart = ParseExpression();
+ ParseCXXCondition(Second, SecondVar, ForLoc, true);
+ else {
+ Second = ParseExpression();
+ if (!Second.isInvalid())
+ Second = Actions.ActOnBooleanCondition(CurScope, ForLoc,
+ move(Second));
+ }
+ SecondPartIsInvalid = Second.isInvalid();
+ SecondPart = Actions.MakeFullExpr(Second);
}
if (Tok.is(tok::semi)) {
ConsumeToken();
} else {
- if (!SecondPart.isInvalid() || SecondVar.get())
+ if (!SecondPartIsInvalid || SecondVar.get())
Diag(Tok, diag::err_expected_semi_for);
SkipUntil(tok::semi);
}
// Parse the third part of the for specifier.
- if (Tok.isNot(tok::r_paren)) // for (...;...;)
- ThirdPart = ParseExpression();
+ if (Tok.isNot(tok::r_paren)) { // for (...;...;)
+ OwningExprResult Third = ParseExpression();
+ ThirdPart = Actions.MakeFullExpr(Third);
+ }
}
// Match the ')'.
SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
@@ -1085,15 +1112,14 @@ Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) {
return StmtError();
if (!ForEach)
- return Actions.ActOnForStmt(ForLoc, LParenLoc, move(FirstPart),
- Actions.MakeFullExpr(SecondPart), SecondVar,
- Actions.MakeFullExpr(ThirdPart), RParenLoc,
- move(Body));
-
- return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc,
- move(FirstPart),
- move(SecondPart),
- RParenLoc, move(Body));
+ return Actions.ActOnForStmt(ForLoc, LParenLoc, move(FirstPart), SecondPart,
+ SecondVar, ThirdPart, RParenLoc, move(Body));
+
+ // FIXME: It isn't clear how to communicate the late destruction of
+ // C++ temporaries used to create the collection.
+ return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc, move(FirstPart),
+ move(Collection), RParenLoc,
+ move(Body));
}
/// ParseGotoStatement
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index ff69953..c87ddad 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -201,7 +201,7 @@ Parser::ParseSingleDeclarationAfterTemplate(
if (Tok.is(tok::semi)) {
DeclEnd = ConsumeToken();
- DeclPtrTy Decl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+ DeclPtrTy Decl = Actions.ParsedFreeStandingDeclSpec(CurScope, AS, DS);
DS.complete(Decl);
return Decl;
}
@@ -902,10 +902,12 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
ConsumeToken(); // the identifier
if (isEndOfTemplateArgument(Tok)) {
+ bool MemberOfUnknownSpecialization;
TemplateNameKind TNK = Actions.isTemplateName(CurScope, SS, Name,
/*ObjectType=*/0,
/*EnteringContext=*/false,
- Template);
+ Template,
+ MemberOfUnknownSpecialization);
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.
@@ -966,6 +968,37 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() {
ExprArg.release(), Loc);
}
+/// \brief Determine whether the current tokens can only be parsed as a
+/// template argument list (starting with the '<') and never as a '<'
+/// expression.
+bool Parser::IsTemplateArgumentList(unsigned Skip) {
+ struct AlwaysRevertAction : TentativeParsingAction {
+ AlwaysRevertAction(Parser &P) : TentativeParsingAction(P) { }
+ ~AlwaysRevertAction() { Revert(); }
+ } Tentative(*this);
+
+ while (Skip) {
+ ConsumeToken();
+ --Skip;
+ }
+
+ // '<'
+ if (!Tok.is(tok::less))
+ return false;
+ ConsumeToken();
+
+ // An empty template argument list.
+ if (Tok.is(tok::greater))
+ return true;
+
+ // See whether we have declaration specifiers, which indicate a type.
+ while (isCXXDeclarationSpecifier() == TPResult::True())
+ ConsumeToken();
+
+ // If we have a '>' or a ',' then this is a template argument list.
+ return Tok.is(tok::greater) || Tok.is(tok::comma);
+}
+
/// ParseTemplateArgumentList - Parse a C++ template-argument-list
/// (C++ [temp.names]). Returns true if there was an error.
///
diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp
index a6c6d3f..5e64e61 100644
--- a/lib/Parse/ParseTentative.cpp
+++ b/lib/Parse/ParseTentative.cpp
@@ -753,6 +753,7 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() {
case tok::kw___cdecl:
case tok::kw___stdcall:
case tok::kw___fastcall:
+ case tok::kw___thiscall:
case tok::kw___w64:
case tok::kw___ptr64:
case tok::kw___forceinline:
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 6dbb99e..2968970 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -33,6 +33,11 @@ Parser::Parser(Preprocessor &pp, Action &actions)
// Add #pragma handlers. These are removed and destroyed in the
// destructor.
+ OptionsHandler.reset(new
+ PragmaOptionsHandler(&PP.getIdentifierTable().get("options"),
+ actions));
+ PP.AddPragmaHandler(0, OptionsHandler.get());
+
PackHandler.reset(new
PragmaPackHandler(&PP.getIdentifierTable().get("pack"), actions));
PP.AddPragmaHandler(0, PackHandler.get());
@@ -134,7 +139,7 @@ SourceLocation Parser::MatchRHSPunctuation(tok::TokenKind RHSTok,
/// returned.
bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID,
const char *Msg, tok::TokenKind SkipToTok) {
- if (Tok.is(ExpectedTok)) {
+ if (Tok.is(ExpectedTok) || Tok.is(tok::code_completion)) {
ConsumeAnyToken();
return false;
}
@@ -189,7 +194,11 @@ bool Parser::SkipUntil(const tok::TokenKind *Toks, unsigned NumToks,
case tok::eof:
// Ran out of tokens.
return false;
-
+
+ case tok::code_completion:
+ ConsumeToken();
+ return false;
+
case tok::l_paren:
// Recursively skip properly-nested parens.
ConsumeParen();
@@ -294,6 +303,8 @@ Parser::~Parser() {
delete ScopeCache[i];
// Remove the pragma handlers we installed.
+ PP.RemovePragmaHandler(0, OptionsHandler.get());
+ OptionsHandler.reset();
PP.RemovePragmaHandler(0, PackHandler.get());
PackHandler.reset();
PP.RemovePragmaHandler(0, UnusedHandler.get());
@@ -447,7 +458,7 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr)
Actions.CodeCompleteOrdinaryName(CurScope,
ObjCImpDecl? Action::CCC_ObjCImplementation
: Action::CCC_Namespace);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
return ParseExternalDeclaration(Attr);
case tok::kw_using:
case tok::kw_namespace:
@@ -538,7 +549,7 @@ Parser::ParseDeclarationOrFunctionDefinition(ParsingDeclSpec &DS,
// declaration-specifiers init-declarator-list[opt] ';'
if (Tok.is(tok::semi)) {
ConsumeToken();
- DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+ DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, AS, DS);
DS.complete(TheDecl);
return Actions.ConvertDeclToDeclGroup(TheDecl);
}
@@ -980,10 +991,11 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
TemplateTy Template;
UnqualifiedId TemplateName;
TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
+ bool MemberOfUnknownSpecialization;
if (TemplateNameKind TNK
= Actions.isTemplateName(CurScope, SS, TemplateName,
/*ObjectType=*/0, EnteringContext,
- Template)) {
+ Template, MemberOfUnknownSpecialization)) {
// Consume the identifier.
ConsumeToken();
if (AnnotateTemplateIdToken(Template, TNK, &SS, TemplateName)) {
@@ -1071,6 +1083,22 @@ bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) {
return false;
}
+void Parser::CodeCompletionRecovery() {
+ for (Scope *S = CurScope; S; S = S->getParent()) {
+ if (S->getFlags() & Scope::FnScope) {
+ Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_RecoveryInFunction);
+ return;
+ }
+
+ if (S->getFlags() & Scope::ClassScope) {
+ Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Class);
+ return;
+ }
+ }
+
+ Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Namespace);
+}
+
// Anchor the Parser::FieldCallback vtable to this translation unit.
// We use a spurious method instead of the destructor because
// destroying FieldCallbacks can actually be slightly
OpenPOWER on IntegriCloud