summaryrefslogtreecommitdiffstats
path: root/lib/Parse/ParseDecl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Parse/ParseDecl.cpp')
-rw-r--r--lib/Parse/ParseDecl.cpp681
1 files changed, 415 insertions, 266 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 555fcf0..5a7fc7e 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -29,13 +29,14 @@ using namespace clang;
/// specifier-qualifier-list abstract-declarator[opt]
///
/// Called type-id in C++.
-TypeResult Parser::ParseTypeName(SourceRange *Range) {
+TypeResult Parser::ParseTypeName(SourceRange *Range,
+ Declarator::TheContext Context) {
// Parse the common declaration-specifiers piece.
DeclSpec DS;
ParseSpecifierQualifierList(DS);
// Parse the abstract-declarator, if present.
- Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ Declarator DeclaratorInfo(DS, Context);
ParseDeclarator(DeclaratorInfo);
if (Range)
*Range = DeclaratorInfo.getSourceRange();
@@ -82,21 +83,20 @@ TypeResult Parser::ParseTypeName(SourceRange *Range) {
/// attributes are very simple in practice. Until we find a bug, I don't see
/// a pressing need to implement the 2 token lookahead.
-AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) {
+void Parser::ParseGNUAttributes(ParsedAttributes &attrs,
+ SourceLocation *endLoc) {
assert(Tok.is(tok::kw___attribute) && "Not a GNU attribute list!");
- AttributeList *CurrAttr = 0;
-
while (Tok.is(tok::kw___attribute)) {
ConsumeToken();
if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
"attribute")) {
SkipUntil(tok::r_paren, true); // skip until ) or ;
- return CurrAttr;
+ return;
}
if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "(")) {
SkipUntil(tok::r_paren, true); // skip until ) or ;
- return CurrAttr;
+ return;
}
// Parse the attribute-list. e.g. __attribute__(( weak, alias("__f") ))
while (Tok.is(tok::identifier) || isDeclarationSpecifier() ||
@@ -122,8 +122,8 @@ AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) {
if (Tok.is(tok::r_paren)) {
// __attribute__(( mode(byte) ))
ConsumeParen(); // ignore the right paren loc for now
- CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc,
- ParmName, ParmLoc, 0, 0, CurrAttr);
+ attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc,
+ ParmName, ParmLoc, 0, 0));
} else if (Tok.is(tok::comma)) {
ConsumeToken();
// __attribute__(( format(printf, 1, 2) ))
@@ -146,10 +146,9 @@ AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) {
}
if (ArgExprsOk && Tok.is(tok::r_paren)) {
ConsumeParen(); // ignore the right paren loc for now
- CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0,
+ attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0,
AttrNameLoc, ParmName, ParmLoc,
- ArgExprs.take(), ArgExprs.size(),
- CurrAttr);
+ ArgExprs.take(), ArgExprs.size()));
}
}
} else { // not an identifier
@@ -158,8 +157,8 @@ AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) {
// parse a possibly empty comma separated list of expressions
// __attribute__(( nonnull() ))
ConsumeParen(); // ignore the right paren loc for now
- CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc,
- 0, SourceLocation(), 0, 0, CurrAttr);
+ attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc,
+ 0, SourceLocation(), 0, 0));
break;
case tok::kw_char:
case tok::kw_wchar_t:
@@ -174,10 +173,12 @@ AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) {
case tok::kw_float:
case tok::kw_double:
case tok::kw_void:
- case tok::kw_typeof:
- CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc,
- 0, SourceLocation(), 0, 0, CurrAttr);
- if (CurrAttr->getKind() == AttributeList::AT_IBOutletCollection)
+ case tok::kw_typeof: {
+ AttributeList *attr
+ = AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc,
+ 0, SourceLocation(), 0, 0);
+ attrs.add(attr);
+ if (attr->getKind() == AttributeList::AT_IBOutletCollection)
Diag(Tok, diag::err_iboutletcollection_builtintype);
// If it's a builtin type name, eat it and expect a rparen
// __attribute__(( vec_type_hint(char) ))
@@ -185,6 +186,7 @@ AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) {
if (Tok.is(tok::r_paren))
ConsumeParen();
break;
+ }
default:
// __attribute__(( aligned(16) ))
ExprVector ArgExprs(Actions);
@@ -207,17 +209,16 @@ AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) {
// Match the ')'.
if (ArgExprsOk && Tok.is(tok::r_paren)) {
ConsumeParen(); // ignore the right paren loc for now
- CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0,
- AttrNameLoc, 0, SourceLocation(), ArgExprs.take(),
- ArgExprs.size(),
- CurrAttr);
+ attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0,
+ AttrNameLoc, 0, SourceLocation(),
+ ArgExprs.take(), ArgExprs.size()));
}
break;
}
}
} else {
- CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc,
- 0, SourceLocation(), 0, 0, CurrAttr);
+ attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc,
+ 0, SourceLocation(), 0, 0));
}
}
if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
@@ -226,10 +227,9 @@ AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) {
if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) {
SkipUntil(tok::r_paren, false);
}
- if (EndLoc)
- *EndLoc = Loc;
+ if (endLoc)
+ *endLoc = Loc;
}
- return CurrAttr;
}
/// ParseMicrosoftDeclSpec - Parse an __declspec construct
@@ -241,14 +241,14 @@ AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) {
/// extended-decl-modifier[opt]
/// extended-decl-modifier extended-decl-modifier-seq
-AttributeList* Parser::ParseMicrosoftDeclSpec(AttributeList *CurrAttr) {
+void Parser::ParseMicrosoftDeclSpec(ParsedAttributes &attrs) {
assert(Tok.is(tok::kw___declspec) && "Not a declspec!");
ConsumeToken();
if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
"declspec")) {
SkipUntil(tok::r_paren, true); // skip until ) or ;
- return CurrAttr;
+ return;
}
while (Tok.getIdentifierInfo()) {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
@@ -260,23 +260,22 @@ AttributeList* Parser::ParseMicrosoftDeclSpec(AttributeList *CurrAttr) {
ExprResult ArgExpr(ParseAssignmentExpression());
if (!ArgExpr.isInvalid()) {
Expr *ExprList = ArgExpr.take();
- CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
- SourceLocation(), &ExprList, 1,
- CurrAttr, true);
+ attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
+ SourceLocation(), &ExprList, 1, true));
}
if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
SkipUntil(tok::r_paren, false);
} else {
- CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc,
- 0, SourceLocation(), 0, 0, CurrAttr, true);
+ attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc,
+ 0, SourceLocation(), 0, 0, true));
}
}
if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
SkipUntil(tok::r_paren, false);
- return CurrAttr;
+ return;
}
-AttributeList* Parser::ParseMicrosoftTypeAttributes(AttributeList *CurrAttr) {
+void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) {
// 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) ||
@@ -287,21 +286,34 @@ AttributeList* Parser::ParseMicrosoftTypeAttributes(AttributeList *CurrAttr) {
if (Tok.is(tok::kw___ptr64) || Tok.is(tok::kw___w64))
// FIXME: Support these properly!
continue;
- CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
- SourceLocation(), 0, 0, CurrAttr, true);
+ attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
+ SourceLocation(), 0, 0, true));
}
- return CurrAttr;
}
-AttributeList* Parser::ParseBorlandTypeAttributes(AttributeList *CurrAttr) {
+void Parser::ParseBorlandTypeAttributes(ParsedAttributes &attrs) {
// Treat these like attributes
while (Tok.is(tok::kw___pascal)) {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
- CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
- SourceLocation(), 0, 0, CurrAttr, true);
+ attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
+ SourceLocation(), 0, 0, true));
+ }
+}
+
+void Parser::ParseOpenCLAttributes(ParsedAttributes &attrs) {
+ // Treat these like attributes
+ while (Tok.is(tok::kw___kernel)) {
+ SourceLocation AttrNameLoc = ConsumeToken();
+ attrs.add(AttrFactory.Create(PP.getIdentifierInfo("opencl_kernel_function"),
+ AttrNameLoc, 0, AttrNameLoc, 0,
+ SourceLocation(), 0, 0, false));
}
- return CurrAttr;
+}
+
+void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs) {
+ Diag(attrs.Range.getBegin(), diag::err_attributes_not_allowed)
+ << attrs.Range;
}
/// ParseDeclaration - Parse a full 'declaration', which consists of
@@ -320,48 +332,43 @@ AttributeList* Parser::ParseBorlandTypeAttributes(AttributeList *CurrAttr) {
/// [C++0x] static_assert-declaration
/// others... [FIXME]
///
-Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context,
+Parser::DeclGroupPtrTy Parser::ParseDeclaration(StmtVector &Stmts,
+ unsigned Context,
SourceLocation &DeclEnd,
- CXX0XAttributeList Attr) {
+ ParsedAttributesWithRange &attrs) {
ParenBraceBracketBalancer BalancerRAIIObj(*this);
Decl *SingleDecl = 0;
switch (Tok.getKind()) {
case tok::kw_template:
case tok::kw_export:
- if (Attr.HasAttr)
- Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
- << Attr.Range;
+ ProhibitAttributes(attrs);
SingleDecl = ParseDeclarationStartingWithTemplate(Context, DeclEnd);
break;
case tok::kw_inline:
// Could be the start of an inline namespace. Allowed as an ext in C++03.
if (getLang().CPlusPlus && NextToken().is(tok::kw_namespace)) {
- if (Attr.HasAttr)
- Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
- << Attr.Range;
+ ProhibitAttributes(attrs);
SourceLocation InlineLoc = ConsumeToken();
SingleDecl = ParseNamespace(Context, DeclEnd, InlineLoc);
break;
}
- return ParseSimpleDeclaration(Context, DeclEnd, Attr.AttrList, true);
+ return ParseSimpleDeclaration(Stmts, Context, DeclEnd, attrs,
+ true);
case tok::kw_namespace:
- if (Attr.HasAttr)
- Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
- << Attr.Range;
+ ProhibitAttributes(attrs);
SingleDecl = ParseNamespace(Context, DeclEnd);
break;
case tok::kw_using:
- SingleDecl = ParseUsingDirectiveOrDeclaration(Context, DeclEnd, Attr);
+ SingleDecl = ParseUsingDirectiveOrDeclaration(Context, ParsedTemplateInfo(),
+ DeclEnd, attrs);
break;
case tok::kw_static_assert:
- if (Attr.HasAttr)
- Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
- << Attr.Range;
+ ProhibitAttributes(attrs);
SingleDecl = ParseStaticAssertDeclaration(DeclEnd);
break;
default:
- return ParseSimpleDeclaration(Context, DeclEnd, Attr.AttrList, true);
+ return ParseSimpleDeclaration(Stmts, Context, DeclEnd, attrs, true);
}
// This routine returns a DeclGroup, if the thing we parsed only contains a
@@ -376,16 +383,19 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context,
///
/// If RequireSemi is false, this does not check for a ';' at the end of the
/// declaration. If it is true, it checks for and eats it.
-Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context,
+Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(StmtVector &Stmts,
+ unsigned Context,
SourceLocation &DeclEnd,
- AttributeList *Attr,
+ ParsedAttributes &attrs,
bool RequireSemi) {
// Parse the common declaration-specifiers piece.
ParsingDeclSpec DS(*this);
- if (Attr)
- DS.AddAttributes(Attr);
+ DS.takeAttributesFrom(attrs);
ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none,
- getDeclSpecContextFromDeclaratorContext(Context));
+ getDeclSpecContextFromDeclaratorContext(Context));
+ StmtResult R = Actions.ActOnVlaStmt(DS);
+ if (R.isUsable())
+ Stmts.push_back(R.release());
// C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
// declaration-specifiers init-declarator-list[opt] ';'
@@ -474,11 +484,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
// short __attribute__((common)) var; -> declspec
// short var __attribute__((common)); -> declarator
// short x, __attribute__((common)) var; -> declarator
- if (Tok.is(tok::kw___attribute)) {
- SourceLocation Loc;
- AttributeList *AttrList = ParseGNUAttributes(&Loc);
- D.AddAttributes(AttrList, Loc);
- }
+ MaybeParseGNUAttributes(D);
ParseDeclarator(D);
@@ -547,12 +553,7 @@ Decl *Parser::ParseDeclarationAfterDeclarator(Declarator &D,
D.SetRangeEnd(Loc);
}
- // If attributes are present, parse them.
- if (Tok.is(tok::kw___attribute)) {
- SourceLocation Loc;
- AttributeList *AttrList = ParseGNUAttributes(&Loc);
- D.AddAttributes(AttrList, Loc);
- }
+ MaybeParseGNUAttributes(D);
// Inform the current actions module that we just parsed this declarator.
Decl *ThisDecl = 0;
@@ -586,11 +587,19 @@ Decl *Parser::ParseDeclarationAfterDeclarator(Declarator &D,
}
}
+ bool TypeContainsAuto =
+ D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto;
+
// Parse declarator '=' initializer.
- if (Tok.is(tok::equal)) {
+ if (isTokenEqualOrMistypedEqualEqual(
+ diag::err_invalid_equalequal_after_declarator)) {
ConsumeToken();
- if (getLang().CPlusPlus0x && Tok.is(tok::kw_delete)) {
+ if (Tok.is(tok::kw_delete)) {
SourceLocation DelLoc = ConsumeToken();
+
+ if (!getLang().CPlusPlus0x)
+ Diag(DelLoc, diag::warn_deleted_function_accepted_as_extension);
+
Actions.SetDeclDeleted(ThisDecl, DelLoc);
} else {
if (getLang().CPlusPlus && D.getCXXScopeSpec().isSet()) {
@@ -616,7 +625,8 @@ Decl *Parser::ParseDeclarationAfterDeclarator(Declarator &D,
SkipUntil(tok::comma, true, true);
Actions.ActOnInitializerError(ThisDecl);
} else
- Actions.AddInitializerToDecl(ThisDecl, Init.take());
+ Actions.AddInitializerToDecl(ThisDecl, Init.take(),
+ /*DirectInit=*/false, TypeContainsAuto);
}
} else if (Tok.is(tok::l_paren)) {
// Parse C++ direct initializer: '(' expression-list ')'
@@ -650,12 +660,11 @@ Decl *Parser::ParseDeclarationAfterDeclarator(Declarator &D,
Actions.AddCXXDirectInitializerToDecl(ThisDecl, LParenLoc,
move_arg(Exprs),
- CommaLocs.data(), RParenLoc);
+ RParenLoc,
+ TypeContainsAuto);
}
} else {
- bool TypeContainsUndeducedAuto =
- D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto;
- Actions.ActOnUninitializedDecl(ThisDecl, TypeContainsUndeducedAuto);
+ Actions.ActOnUninitializedDecl(ThisDecl, TypeContainsAuto);
}
return ThisDecl;
@@ -675,7 +684,7 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS) {
// Validate declspec for type-name.
unsigned Specs = DS.getParsedSpecifiers();
if (Specs == DeclSpec::PQ_None && !DS.getNumProtocolQualifiers() &&
- !DS.getAttributes())
+ !DS.hasAttributes())
Diag(Tok, diag::err_typename_requires_specqual);
// Issue diagnostic and remove storage class if present.
@@ -868,6 +877,7 @@ Parser::getDeclSpecContextFromDeclaratorContext(unsigned Context) {
/// [C99] 'inline'
/// [C++] 'virtual'
/// [C++] 'explicit'
+/// [OpenCL] '__kernel'
/// 'friend': [C++ dcl.friend]
/// 'constexpr': [C++0x dcl.constexpr]
@@ -877,6 +887,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
AccessSpecifier AS,
DeclSpecContext DSContext) {
DS.SetRangeStart(Tok.getLocation());
+ DS.SetRangeEnd(Tok.getLocation());
while (1) {
bool isInvalid = false;
const char *PrevSpec = 0;
@@ -905,13 +916,16 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
= DSContext == DSC_top_level ||
(DSContext == DSC_class && DS.isFriendSpecified());
- Actions.CodeCompleteDeclarator(getCurScope(), AllowNonIdentifiers,
- AllowNestedNameSpecifiers);
+ Actions.CodeCompleteDeclSpec(getCurScope(), DS,
+ AllowNonIdentifiers,
+ AllowNestedNameSpecifiers);
ConsumeCodeCompletionToken();
return;
}
- if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate)
+ if (getCurScope()->getFnParent() || getCurScope()->getBlockParent())
+ CCC = Sema::PCC_LocalDeclarationSpecifiers;
+ else if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate)
CCC = DSContext == DSC_class? Sema::PCC_MemberTemplate
: Sema::PCC_Template;
else if (DSContext == DSC_class)
@@ -1005,7 +1019,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
ConsumeToken(); // The C++ scope.
if (Tok.getAnnotationValue()) {
ParsedType T = getTypeAnnotation(Tok);
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc,
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename,
+ Tok.getAnnotationEndLoc(),
PrevSpec, DiagID, T);
}
else
@@ -1080,20 +1095,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// Objective-C supports syntax of the form 'id<proto1,proto2>' where 'id'
// is a specific typedef and 'itf<proto1,proto2>' where 'itf' is an
- // Objective-C interface. If we don't have Objective-C or a '<', this is
- // just a normal reference to a typedef name.
- if (!Tok.is(tok::less) || !getLang().ObjC1)
- continue;
-
- SourceLocation LAngleLoc, EndProtoLoc;
- llvm::SmallVector<Decl *, 8> ProtocolDecl;
- llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
- ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
- LAngleLoc, EndProtoLoc);
- DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(),
- ProtocolLocs.data(), LAngleLoc);
-
- DS.SetRangeEnd(EndProtoLoc);
+ // Objective-C interface.
+ if (Tok.is(tok::less) && getLang().ObjC1)
+ ParseObjCProtocolQualifiers(DS);
+
continue;
}
@@ -1150,21 +1155,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// Objective-C supports syntax of the form 'id<proto1,proto2>' where 'id'
// is a specific typedef and 'itf<proto1,proto2>' where 'itf' is an
- // Objective-C interface. If we don't have Objective-C or a '<', this is
- // just a normal reference to a typedef name.
- if (!Tok.is(tok::less) || !getLang().ObjC1)
- continue;
-
- SourceLocation LAngleLoc, EndProtoLoc;
- llvm::SmallVector<Decl *, 8> ProtocolDecl;
- llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
- ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
- LAngleLoc, EndProtoLoc);
- DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(),
- ProtocolLocs.data(), LAngleLoc);
-
- DS.SetRangeEnd(EndProtoLoc);
-
+ // Objective-C interface.
+ if (Tok.is(tok::less) && getLang().ObjC1)
+ ParseObjCProtocolQualifiers(DS);
+
// Need to support trailing type qualifiers (e.g. "id<p> const").
// If a type specifier follows, it will be diagnosed elsewhere.
continue;
@@ -1196,12 +1190,12 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// GNU attributes support.
case tok::kw___attribute:
- DS.AddAttributes(ParseGNUAttributes());
+ ParseGNUAttributes(DS.getAttributes());
continue;
// Microsoft declspec support.
case tok::kw___declspec:
- DS.AddAttributes(ParseMicrosoftDeclSpec());
+ ParseMicrosoftDeclSpec(DS.getAttributes());
continue;
// Microsoft single token adornments.
@@ -1215,34 +1209,39 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
case tok::kw___stdcall:
case tok::kw___fastcall:
case tok::kw___thiscall:
- DS.AddAttributes(ParseMicrosoftTypeAttributes());
+ ParseMicrosoftTypeAttributes(DS.getAttributes());
continue;
// Borland single token adornments.
case tok::kw___pascal:
- DS.AddAttributes(ParseBorlandTypeAttributes());
+ ParseBorlandTypeAttributes(DS.getAttributes());
+ continue;
+
+ // OpenCL single token adornments.
+ case tok::kw___kernel:
+ ParseOpenCLAttributes(DS.getAttributes());
continue;
// storage-class-specifier
case tok::kw_typedef:
isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, Loc, PrevSpec,
- DiagID);
+ DiagID, getLang());
break;
case tok::kw_extern:
if (DS.isThreadSpecified())
Diag(Tok, diag::ext_thread_before) << "extern";
isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_extern, Loc, PrevSpec,
- DiagID);
+ DiagID, getLang());
break;
case tok::kw___private_extern__:
isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_private_extern, Loc,
- PrevSpec, DiagID);
+ PrevSpec, DiagID, getLang());
break;
case tok::kw_static:
if (DS.isThreadSpecified())
Diag(Tok, diag::ext_thread_before) << "static";
isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_static, Loc, PrevSpec,
- DiagID);
+ DiagID, getLang());
break;
case tok::kw_auto:
if (getLang().CPlusPlus0x)
@@ -1250,15 +1249,15 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
DiagID);
else
isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec,
- DiagID);
+ DiagID, getLang());
break;
case tok::kw_register:
isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_register, Loc, PrevSpec,
- DiagID);
+ DiagID, getLang());
break;
case tok::kw_mutable:
isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_mutable, Loc, PrevSpec,
- DiagID);
+ DiagID, getLang());
break;
case tok::kw___thread:
isInvalid = DS.SetStorageClassSpecThread(Loc, PrevSpec, DiagID);
@@ -1354,8 +1353,16 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
break;
case tok::kw_bool:
case tok::kw__Bool:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec,
- DiagID);
+ if (Tok.is(tok::kw_bool) &&
+ DS.getTypeSpecType() != DeclSpec::TST_unspecified &&
+ DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
+ PrevSpec = ""; // Not used by the diagnostic.
+ DiagID = diag::err_bool_redeclaration;
+ isInvalid = true;
+ } else {
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec,
+ DiagID);
+ }
break;
case tok::kw__Decimal32:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, Loc, PrevSpec,
@@ -1432,23 +1439,14 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
if (DS.hasTypeSpecifier() || !getLang().ObjC1)
goto DoneWithDeclSpec;
- {
- SourceLocation LAngleLoc, EndProtoLoc;
- llvm::SmallVector<Decl *, 8> ProtocolDecl;
- llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
- ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
- LAngleLoc, EndProtoLoc);
- DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(),
- ProtocolLocs.data(), LAngleLoc);
- DS.SetRangeEnd(EndProtoLoc);
-
+ if (!ParseObjCProtocolQualifiers(DS))
Diag(Loc, diag::warn_objc_protocol_qualifier_missing_id)
<< FixItHint::CreateInsertion(Loc, "id")
- << SourceRange(Loc, EndProtoLoc);
- // Need to support trailing type qualifiers (e.g. "id<p> const").
- // If a type specifier follows, it will be diagnosed elsewhere.
- continue;
- }
+ << SourceRange(Loc, DS.getSourceRange().getEnd());
+
+ // Need to support trailing type qualifiers (e.g. "id<p> const").
+ // If a type specifier follows, it will be diagnosed elsewhere.
+ continue;
}
// If the specifier wasn't legal, issue a diagnostic.
if (isInvalid) {
@@ -1552,7 +1550,8 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
// simple-type-specifier:
case tok::annot_typename: {
if (ParsedType T = getTypeAnnotation(Tok)) {
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename,
+ Tok.getAnnotationEndLoc(), PrevSpec,
DiagID, T);
} else
DS.SetTypeSpecError();
@@ -1563,18 +1562,9 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
// is a specific typedef and 'itf<proto1,proto2>' where 'itf' is an
// Objective-C interface. If we don't have Objective-C or a '<', this is
// just a normal reference to a typedef name.
- if (!Tok.is(tok::less) || !getLang().ObjC1)
- return true;
-
- SourceLocation LAngleLoc, EndProtoLoc;
- llvm::SmallVector<Decl *, 8> ProtocolDecl;
- llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
- ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
- LAngleLoc, EndProtoLoc);
- DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(),
- ProtocolLocs.data(), LAngleLoc);
-
- DS.SetRangeEnd(EndProtoLoc);
+ if (Tok.is(tok::less) && getLang().ObjC1)
+ ParseObjCProtocolQualifiers(DS);
+
return true;
}
@@ -1706,11 +1696,11 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
case tok::kw___stdcall:
case tok::kw___fastcall:
case tok::kw___thiscall:
- DS.AddAttributes(ParseMicrosoftTypeAttributes());
+ ParseMicrosoftTypeAttributes(DS.getAttributes());
return true;
case tok::kw___pascal:
- DS.AddAttributes(ParseBorlandTypeAttributes());
+ ParseBorlandTypeAttributes(DS.getAttributes());
return true;
default:
@@ -1756,7 +1746,6 @@ ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) {
}
// Parse the common specifier-qualifiers-list piece.
- SourceLocation DSStart = Tok.getLocation();
ParseSpecifierQualifierList(DS);
// If there are no declarators, this is a free-standing declaration
@@ -1773,11 +1762,8 @@ ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) {
FieldDeclarator DeclaratorInfo(DS);
// Attributes are only allowed here on successive declarators.
- if (!FirstDeclarator && Tok.is(tok::kw___attribute)) {
- SourceLocation Loc;
- AttributeList *AttrList = ParseGNUAttributes(&Loc);
- DeclaratorInfo.D.AddAttributes(AttrList, Loc);
- }
+ if (!FirstDeclarator)
+ MaybeParseGNUAttributes(DeclaratorInfo.D);
/// struct-declarator: declarator
/// struct-declarator: declarator[opt] ':' constant-expression
@@ -1797,11 +1783,7 @@ ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) {
}
// If attributes exist after the declarator, parse them.
- if (Tok.is(tok::kw___attribute)) {
- SourceLocation Loc;
- AttributeList *AttrList = ParseGNUAttributes(&Loc);
- DeclaratorInfo.D.AddAttributes(AttrList, Loc);
- }
+ MaybeParseGNUAttributes(DeclaratorInfo.D);
// We're done with this declarator; invoke the callback.
Decl *D = Fields.invoke(DeclaratorInfo);
@@ -1922,20 +1904,18 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc);
- llvm::OwningPtr<AttributeList> AttrList;
+ ParsedAttributes attrs;
// If attributes exist after struct contents, parse them.
- if (Tok.is(tok::kw___attribute))
- AttrList.reset(ParseGNUAttributes());
+ MaybeParseGNUAttributes(attrs);
Actions.ActOnFields(getCurScope(),
RecordLoc, TagDecl, FieldDecls.data(), FieldDecls.size(),
LBraceLoc, RBraceLoc,
- AttrList.get());
+ attrs.getList());
StructScope.Exit();
Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, RBraceLoc);
}
-
/// ParseEnumSpecifier
/// enum-specifier: [C99 6.7.2.2]
/// 'enum' identifier[opt] '{' enumerator-list '}'
@@ -1945,6 +1925,21 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
/// 'enum' identifier
/// [GNU] 'enum' attributes[opt] identifier
///
+/// [C++0x] enum-head '{' enumerator-list[opt] '}'
+/// [C++0x] enum-head '{' enumerator-list ',' '}'
+///
+/// enum-head: [C++0x]
+/// enum-key attributes[opt] identifier[opt] enum-base[opt]
+/// enum-key attributes[opt] nested-name-specifier identifier enum-base[opt]
+///
+/// enum-key: [C++0x]
+/// 'enum'
+/// 'enum' 'class'
+/// 'enum' 'struct'
+///
+/// enum-base: [C++0x]
+/// ':' type-specifier-seq
+///
/// [C++] elaborated-type-specifier:
/// [C++] 'enum' '::'[opt] nested-name-specifier[opt] identifier
///
@@ -1958,10 +1953,9 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
ConsumeCodeCompletionToken();
}
- llvm::OwningPtr<AttributeList> Attr;
// If attributes exist after tag, parse them.
- if (Tok.is(tok::kw___attribute))
- Attr.reset(ParseGNUAttributes());
+ ParsedAttributes attrs;
+ MaybeParseGNUAttributes(attrs);
CXXScopeSpec &SS = DS.getTypeSpecScope();
if (getLang().CPlusPlus) {
@@ -1979,6 +1973,16 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
}
}
+ bool IsScopedEnum = false;
+ bool IsScopedUsingClassTag = false;
+
+ if (getLang().CPlusPlus0x &&
+ (Tok.is(tok::kw_class) || Tok.is(tok::kw_struct))) {
+ IsScopedEnum = true;
+ IsScopedUsingClassTag = Tok.is(tok::kw_class);
+ ConsumeToken();
+ }
+
// Must have either 'enum name' or 'enum {...}'.
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::l_brace)) {
Diag(Tok, diag::err_expected_ident_lbrace);
@@ -1996,6 +2000,69 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
NameLoc = ConsumeToken();
}
+ if (!Name && IsScopedEnum) {
+ // C++0x 7.2p2: The optional identifier shall not be omitted in the
+ // declaration of a scoped enumeration.
+ Diag(Tok, diag::err_scoped_enum_missing_identifier);
+ IsScopedEnum = false;
+ IsScopedUsingClassTag = false;
+ }
+
+ TypeResult BaseType;
+
+ // Parse the fixed underlying type.
+ if (getLang().CPlusPlus0x && Tok.is(tok::colon)) {
+ bool PossibleBitfield = false;
+ if (getCurScope()->getFlags() & Scope::ClassScope) {
+ // If we're in class scope, this can either be an enum declaration with
+ // an underlying type, or a declaration of a bitfield member. We try to
+ // use a simple disambiguation scheme first to catch the common cases
+ // (integer literal, sizeof); if it's still ambiguous, we then consider
+ // anything that's a simple-type-specifier followed by '(' as an
+ // expression. This suffices because function types are not valid
+ // underlying types anyway.
+ TPResult TPR = isExpressionOrTypeSpecifierSimple(NextToken().getKind());
+ // If the next token starts an expression, we know we're parsing a
+ // bit-field. This is the common case.
+ if (TPR == TPResult::True())
+ PossibleBitfield = true;
+ // If the next token starts a type-specifier-seq, it may be either a
+ // a fixed underlying type or the start of a function-style cast in C++;
+ // lookahead one more token to see if it's obvious that we have a
+ // fixed underlying type.
+ else if (TPR == TPResult::False() &&
+ GetLookAheadToken(2).getKind() == tok::semi) {
+ // Consume the ':'.
+ ConsumeToken();
+ } else {
+ // We have the start of a type-specifier-seq, so we have to perform
+ // tentative parsing to determine whether we have an expression or a
+ // type.
+ TentativeParsingAction TPA(*this);
+
+ // Consume the ':'.
+ ConsumeToken();
+
+ if (isCXXDeclarationSpecifier() != TPResult::True()) {
+ // We'll parse this as a bitfield later.
+ PossibleBitfield = true;
+ TPA.Revert();
+ } else {
+ // We have a type-specifier-seq.
+ TPA.Commit();
+ }
+ }
+ } else {
+ // Consume the ':'.
+ ConsumeToken();
+ }
+
+ if (!PossibleBitfield) {
+ SourceRange Range;
+ BaseType = ParseTypeName(&Range);
+ }
+ }
+
// There are three options here. If we have 'enum foo;', then this is a
// forward declaration. If we have 'enum foo {...' then this is a
// definition. Otherwise we have something like 'enum foo xyz', a reference.
@@ -2029,10 +2096,12 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
const char *PrevSpec = 0;
unsigned DiagID;
Decl *TagDecl = Actions.ActOnTag(getCurScope(), DeclSpec::TST_enum, TUK,
- StartLoc, SS, Name, NameLoc, Attr.get(),
+ StartLoc, SS, Name, NameLoc, attrs.getList(),
AS,
MultiTemplateParamsArg(Actions),
- Owned, IsDependent);
+ Owned, IsDependent, IsScopedEnum,
+ IsScopedUsingClassTag, BaseType);
+
if (IsDependent) {
// This enum has a dependent nested-name-specifier. Handle it as a
// dependent tag.
@@ -2109,6 +2178,10 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
IdentifierInfo *Ident = Tok.getIdentifierInfo();
SourceLocation IdentLoc = ConsumeToken();
+ // If attributes exist after the enumerator, parse them.
+ ParsedAttributes attrs;
+ MaybeParseGNUAttributes(attrs);
+
SourceLocation EqualLoc;
ExprResult AssignedVal;
if (Tok.is(tok::equal)) {
@@ -2122,11 +2195,19 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
Decl *EnumConstDecl = Actions.ActOnEnumConstant(getCurScope(), EnumDecl,
LastEnumConstDecl,
IdentLoc, Ident,
- EqualLoc,
+ attrs.getList(), EqualLoc,
AssignedVal.release());
EnumConstantDecls.push_back(EnumConstDecl);
LastEnumConstDecl = EnumConstDecl;
+ if (Tok.is(tok::identifier)) {
+ // We're missing a comma between enumerators.
+ SourceLocation Loc = PP.getLocForEndOfToken(PrevTokLocation);
+ Diag(Loc, diag::err_enumerator_list_missing_comma)
+ << FixItHint::CreateInsertion(Loc, ", ");
+ continue;
+ }
+
if (Tok.isNot(tok::comma))
break;
SourceLocation CommaLoc = ConsumeToken();
@@ -2141,14 +2222,13 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
// Eat the }.
SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc);
- llvm::OwningPtr<AttributeList> Attr;
// If attributes exist after the identifier list, parse them.
- if (Tok.is(tok::kw___attribute))
- Attr.reset(ParseGNUAttributes()); // FIXME: where do they do?
+ ParsedAttributes attrs;
+ MaybeParseGNUAttributes(attrs);
Actions.ActOnEnumBody(StartLoc, LBraceLoc, RBraceLoc, EnumDecl,
EnumConstantDecls.data(), EnumConstantDecls.size(),
- getCurScope(), Attr.get());
+ getCurScope(), attrs.getList());
EnumScope.Exit();
Actions.ActOnTagFinishDefinition(getCurScope(), EnumDecl, RBraceLoc);
@@ -2296,7 +2376,10 @@ bool Parser::isTypeSpecifierQualifier() {
/// isDeclarationSpecifier() - Return true if the current token is part of a
/// declaration specifier.
-bool Parser::isDeclarationSpecifier() {
+///
+/// \param DisambiguatingWithExpression True to indicate that the purpose of
+/// this check is to disambiguate between an expression and a declaration.
+bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
switch (Tok.getKind()) {
default: return false;
@@ -2314,6 +2397,16 @@ bool Parser::isDeclarationSpecifier() {
return true;
if (Tok.is(tok::identifier))
return false;
+
+ // If we're in Objective-C and we have an Objective-C class type followed
+ // by an identifier and then either ':' or ']', in a place where an
+ // expression is permitted, then this is probably a class message send
+ // missing the initial '['. In this case, we won't consider this to be
+ // the start of a declaration.
+ if (DisambiguatingWithExpression &&
+ isStartOfObjCClassMessageMissingOpenBracket())
+ return false;
+
return isDeclarationSpecifier();
case tok::coloncolon: // ::foo::bar
@@ -2441,6 +2534,10 @@ bool Parser::isConstructorDeclarator() {
if (SS.isSet() && Actions.ShouldEnterDeclaratorScope(getCurScope(), SS))
DeclScopeObj.EnterDeclaratorScope();
+ // Optionally skip Microsoft attributes.
+ ParsedAttributes Attrs;
+ MaybeParseMicrosoftAttributes(Attrs);
+
// Check whether the next token(s) are part of a declaration
// specifier, in which case we have the start of a parameter and,
// therefore, we know that this is a constructor.
@@ -2466,9 +2563,10 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS,
bool CXX0XAttributesAllowed) {
if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
SourceLocation Loc = Tok.getLocation();
- CXX0XAttributeList Attr = ParseCXX0XAttributes();
+ ParsedAttributesWithRange attrs;
+ ParseCXX0XAttributes(attrs);
if (CXX0XAttributesAllowed)
- DS.AddAttributes(Attr.AttrList);
+ DS.takeAttributesFrom(attrs);
else
Diag(Loc, diag::err_attributes_not_allowed);
}
@@ -2504,19 +2602,19 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS,
case tok::kw___fastcall:
case tok::kw___thiscall:
if (VendorAttributesAllowed) {
- DS.AddAttributes(ParseMicrosoftTypeAttributes());
+ ParseMicrosoftTypeAttributes(DS.getAttributes());
continue;
}
goto DoneWithTypeQuals;
case tok::kw___pascal:
if (VendorAttributesAllowed) {
- DS.AddAttributes(ParseBorlandTypeAttributes());
+ ParseBorlandTypeAttributes(DS.getAttributes());
continue;
}
goto DoneWithTypeQuals;
case tok::kw___attribute:
if (VendorAttributesAllowed) {
- DS.AddAttributes(ParseGNUAttributes());
+ ParseGNUAttributes(DS.getAttributes());
continue; // do *not* consume the next token!
}
// otherwise, FALL THROUGH!
@@ -2602,7 +2700,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
// Sema will have to catch (syntactically invalid) pointers into global
// scope. It has to catch pointers into namespace scope anyway.
D.AddTypeInfo(DeclaratorChunk::getMemberPointer(SS,DS.getTypeQualifiers(),
- Loc, DS.TakeAttributes()),
+ Loc, DS.takeAttributes()),
/* Don't replace range end. */SourceLocation());
return;
}
@@ -2636,12 +2734,12 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
if (Kind == tok::star)
// Remember that we parsed a pointer type, and remember the type-quals.
D.AddTypeInfo(DeclaratorChunk::getPointer(DS.getTypeQualifiers(), Loc,
- DS.TakeAttributes()),
+ DS.takeAttributes()),
SourceLocation());
else
// Remember that we parsed a Block type, and remember the type-quals.
D.AddTypeInfo(DeclaratorChunk::getBlockPointer(DS.getTypeQualifiers(),
- Loc, DS.TakeAttributes()),
+ Loc, DS.takeAttributes()),
SourceLocation());
} else {
// Is a reference
@@ -2650,7 +2748,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
// Complain about rvalue references in C++03, but then go on and build
// the declarator.
if (Kind == tok::ampamp && !getLang().CPlusPlus0x)
- Diag(Loc, diag::err_rvalue_reference);
+ Diag(Loc, diag::ext_rvalue_reference);
// C++ 8.3.2p1: cv-qualified references are ill-formed except when the
// cv-qualifiers are introduced through the use of a typedef or of a
@@ -2693,7 +2791,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
// Remember that we parsed a reference type. It doesn't have type-quals.
D.AddTypeInfo(DeclaratorChunk::getReference(DS.getTypeQualifiers(), Loc,
- DS.TakeAttributes(),
+ DS.takeAttributes(),
Kind == tok::amp),
SourceLocation());
}
@@ -2718,7 +2816,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
/// [C++] declarator-id
///
/// declarator-id: [C++ 8]
-/// id-expression
+/// '...'[opt] id-expression
/// '::'[opt] nested-name-specifier[opt] type-name
///
/// id-expression: [C++ 5.1]
@@ -2748,6 +2846,20 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
DeclScopeObj.EnterDeclaratorScope();
}
+ // C++0x [dcl.fct]p14:
+ // There is a syntactic ambiguity when an ellipsis occurs at the end
+ // of a parameter-declaration-clause without a preceding comma. In
+ // this case, the ellipsis is parsed as part of the
+ // abstract-declarator if the type of the parameter names a template
+ // parameter pack that has not been expanded; otherwise, it is parsed
+ // as part of the parameter-declaration-clause.
+ if (Tok.is(tok::ellipsis) &&
+ !((D.getContext() == Declarator::PrototypeContext ||
+ D.getContext() == Declarator::BlockLiteralContext) &&
+ NextToken().is(tok::r_paren) &&
+ !Actions.containsUnexpandedParameterPacks(D)))
+ D.setEllipsisLoc(ConsumeToken());
+
if (Tok.is(tok::identifier) || Tok.is(tok::kw_operator) ||
Tok.is(tok::annot_template_id) || Tok.is(tok::tilde)) {
// We found something that indicates the start of an unqualified-id.
@@ -2830,12 +2942,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
"Haven't past the location of the identifier yet?");
// Don't parse attributes unless we have an identifier.
- if (D.getIdentifier() && getLang().CPlusPlus0x
- && isCXX0XAttributeSpecifier(true)) {
- SourceLocation AttrEndLoc;
- CXX0XAttributeList Attr = ParseCXX0XAttributes();
- D.AddAttributes(Attr.AttrList, AttrEndLoc);
- }
+ if (D.getIdentifier())
+ MaybeParseCXX0XAttributes(D);
while (1) {
if (Tok.is(tok::l_paren)) {
@@ -2849,7 +2957,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
if (!isCXXFunctionDeclarator(warnIfAmbiguous))
break;
}
- ParseFunctionDeclarator(ConsumeParen(), D);
+ ParsedAttributes attrs;
+ ParseFunctionDeclarator(ConsumeParen(), D, attrs);
} else if (Tok.is(tok::l_square)) {
ParseBracketDeclarator(D);
} else {
@@ -2885,10 +2994,10 @@ void Parser::ParseParenDeclarator(Declarator &D) {
// In either case, we need to eat any attributes to be able to determine what
// sort of paren this is.
//
- llvm::OwningPtr<AttributeList> AttrList;
+ ParsedAttributes attrs;
bool RequiresArg = false;
if (Tok.is(tok::kw___attribute)) {
- AttrList.reset(ParseGNUAttributes());
+ ParseGNUAttributes(attrs);
// We require that the argument list (if this is a non-grouping paren) be
// present even if the attribute list was empty.
@@ -2898,12 +3007,11 @@ void Parser::ParseParenDeclarator(Declarator &D) {
if (Tok.is(tok::kw___cdecl) || Tok.is(tok::kw___stdcall) ||
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()));
+ ParseMicrosoftTypeAttributes(attrs);
}
// Eat any Borland extensions.
- if (Tok.is(tok::kw___pascal)) {
- AttrList.reset(ParseBorlandTypeAttributes(AttrList.take()));
- }
+ if (Tok.is(tok::kw___pascal))
+ ParseBorlandTypeAttributes(attrs);
// If we haven't past the identifier yet (or where the identifier would be
// stored, if this is an abstract declarator), then this is probably just
@@ -2932,15 +3040,15 @@ void Parser::ParseParenDeclarator(Declarator &D) {
if (isGrouping) {
bool hadGroupingParens = D.hasGroupingParens();
D.setGroupingParens(true);
- if (AttrList)
- D.AddAttributes(AttrList.take(), SourceLocation());
+ if (!attrs.empty())
+ D.addAttributes(attrs.getList(), SourceLocation());
ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator);
// Match the ')'.
- SourceLocation Loc = MatchRHSPunctuation(tok::r_paren, StartLoc);
+ SourceLocation EndLoc = MatchRHSPunctuation(tok::r_paren, StartLoc);
+ D.AddTypeInfo(DeclaratorChunk::getParen(StartLoc, EndLoc), EndLoc);
D.setGroupingParens(hadGroupingParens);
- D.SetRangeEnd(Loc);
return;
}
@@ -2950,7 +3058,7 @@ void Parser::ParseParenDeclarator(Declarator &D) {
// ParseFunctionDeclarator to handle of argument list.
D.SetIdentifier(0, Tok.getLocation());
- ParseFunctionDeclarator(StartLoc, D, AttrList.take(), RequiresArg);
+ ParseFunctionDeclarator(StartLoc, D, attrs, RequiresArg);
}
/// ParseFunctionDeclarator - We are after the identifier and have parsed the
@@ -2982,37 +3090,51 @@ void Parser::ParseParenDeclarator(Declarator &D) {
/// '=' assignment-expression
/// [GNU] declaration-specifiers abstract-declarator[opt] attributes
///
-/// For C++, after the parameter-list, it also parses "cv-qualifier-seq[opt]"
-/// and "exception-specification[opt]".
+/// For C++, after the parameter-list, it also parses "cv-qualifier-seq[opt]",
+/// C++0x "ref-qualifier[opt]" and "exception-specification[opt]".
///
void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
- AttributeList *AttrList,
+ ParsedAttributes &attrs,
bool RequiresArg) {
// lparen is already consumed!
assert(D.isPastIdentifier() && "Should not call before identifier!");
+ ParsedType TrailingReturnType;
+
// This parameter list may be empty.
if (Tok.is(tok::r_paren)) {
- if (RequiresArg) {
+ if (RequiresArg)
Diag(Tok, diag::err_argument_required_after_attribute);
- delete AttrList;
- }
SourceLocation RParenLoc = ConsumeParen(); // Eat the closing ')'.
SourceLocation EndLoc = RParenLoc;
// cv-qualifier-seq[opt].
DeclSpec DS;
+ SourceLocation RefQualifierLoc;
+ bool RefQualifierIsLValueRef = true;
bool hasExceptionSpec = false;
SourceLocation ThrowLoc;
bool hasAnyExceptionSpec = false;
llvm::SmallVector<ParsedType, 2> Exceptions;
llvm::SmallVector<SourceRange, 2> ExceptionRanges;
if (getLang().CPlusPlus) {
+ MaybeParseCXX0XAttributes(attrs);
+
ParseTypeQualifierListOpt(DS, false /*no attributes*/);
if (!DS.getSourceRange().getEnd().isInvalid())
EndLoc = DS.getSourceRange().getEnd();
+ // Parse ref-qualifier[opt]
+ if (Tok.is(tok::amp) || Tok.is(tok::ampamp)) {
+ if (!getLang().CPlusPlus0x)
+ Diag(Tok, diag::ext_ref_qualifier);
+
+ RefQualifierIsLValueRef = Tok.is(tok::amp);
+ RefQualifierLoc = ConsumeToken();
+ EndLoc = RefQualifierLoc;
+ }
+
// Parse exception-specification[opt].
if (Tok.is(tok::kw_throw)) {
hasExceptionSpec = true;
@@ -3022,21 +3144,30 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
assert(Exceptions.size() == ExceptionRanges.size() &&
"Produced different number of exception types and ranges.");
}
+
+ // Parse trailing-return-type.
+ if (getLang().CPlusPlus0x && Tok.is(tok::arrow)) {
+ TrailingReturnType = ParseTrailingReturnType().get();
+ }
}
// Remember that we parsed a function type, and remember the attributes.
// int() -> no prototype, no '...'.
- D.AddTypeInfo(DeclaratorChunk::getFunction(/*prototype*/getLang().CPlusPlus,
+ D.AddTypeInfo(DeclaratorChunk::getFunction(attrs,
+ /*prototype*/getLang().CPlusPlus,
/*variadic*/ false,
SourceLocation(),
/*arglist*/ 0, 0,
DS.getTypeQualifiers(),
+ RefQualifierIsLValueRef,
+ RefQualifierLoc,
hasExceptionSpec, ThrowLoc,
hasAnyExceptionSpec,
Exceptions.data(),
ExceptionRanges.data(),
Exceptions.size(),
- LParenLoc, RParenLoc, D),
+ LParenLoc, RParenLoc, D,
+ TrailingReturnType),
EndLoc);
return;
}
@@ -3048,10 +3179,8 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
if (TryAnnotateTypeOrScopeToken() || !Tok.is(tok::annot_typename)) {
// K&R identifier lists can't have typedefs as identifiers, per
// C99 6.7.5.3p11.
- if (RequiresArg) {
+ if (RequiresArg)
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. Get the first
@@ -3101,17 +3230,20 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
break;
}
- SourceLocation DSStart = Tok.getLocation();
-
// Parse the declaration-specifiers.
// Just use the ParsingDeclaration "scope" of the declarator.
DeclSpec DS;
+
+ // Skip any Microsoft attributes before a param.
+ if (getLang().Microsoft && Tok.is(tok::l_square))
+ ParseMicrosoftAttributes(DS.getAttributes());
+
+ SourceLocation DSStart = Tok.getLocation();
// If the caller parsed attributes for the first argument, add them now.
- if (AttrList) {
- DS.AddAttributes(AttrList);
- AttrList = 0; // Only apply the attributes to the first parameter.
- }
+ // Take them so that we only apply the attributes to the first parameter.
+ DS.takeAttributesFrom(attrs);
+
ParseDeclarationSpecifiers(DS);
// Parse the declarator. This is "PrototypeContext", because we must
@@ -3120,11 +3252,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
ParseDeclarator(ParmDecl);
// Parse GNU attributes, if present.
- if (Tok.is(tok::kw___attribute)) {
- SourceLocation Loc;
- AttributeList *AttrList = ParseGNUAttributes(&Loc);
- ParmDecl.AddAttributes(AttrList, Loc);
- }
+ MaybeParseGNUAttributes(ParmDecl);
// Remember this parsed parameter in ParamInfo.
IdentifierInfo *ParmII = ParmDecl.getIdentifier();
@@ -3184,6 +3312,11 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
// Consume the '='.
ConsumeToken();
+ // The argument isn't actually potentially evaluated unless it is
+ // used.
+ EnterExpressionEvaluationContext Eval(Actions,
+ Sema::PotentiallyEvaluatedIfUsed);
+
ExprResult DefArgResult(ParseAssignmentExpression());
if (DefArgResult.isInvalid()) {
Actions.ActOnParamDefaultArgumentError(Param);
@@ -3222,14 +3355,13 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
ConsumeToken();
}
- // Leave prototype scope.
- PrototypeScope.Exit();
-
// If we have the closing ')', eat it.
SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
SourceLocation EndLoc = RParenLoc;
DeclSpec DS;
+ SourceLocation RefQualifierLoc;
+ bool RefQualifierIsLValueRef = true;
bool hasExceptionSpec = false;
SourceLocation ThrowLoc;
bool hasAnyExceptionSpec = false;
@@ -3237,11 +3369,23 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
llvm::SmallVector<SourceRange, 2> ExceptionRanges;
if (getLang().CPlusPlus) {
+ MaybeParseCXX0XAttributes(attrs);
+
// Parse cv-qualifier-seq[opt].
ParseTypeQualifierListOpt(DS, false /*no attributes*/);
if (!DS.getSourceRange().getEnd().isInvalid())
EndLoc = DS.getSourceRange().getEnd();
+ // Parse ref-qualifier[opt]
+ if (Tok.is(tok::amp) || Tok.is(tok::ampamp)) {
+ if (!getLang().CPlusPlus0x)
+ Diag(Tok, diag::ext_ref_qualifier);
+
+ RefQualifierIsLValueRef = Tok.is(tok::amp);
+ RefQualifierLoc = ConsumeToken();
+ EndLoc = RefQualifierLoc;
+ }
+
// Parse exception-specification[opt].
if (Tok.is(tok::kw_throw)) {
hasExceptionSpec = true;
@@ -3251,19 +3395,34 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
assert(Exceptions.size() == ExceptionRanges.size() &&
"Produced different number of exception types and ranges.");
}
+
+ // Parse trailing-return-type.
+ if (getLang().CPlusPlus0x && Tok.is(tok::arrow)) {
+ TrailingReturnType = ParseTrailingReturnType().get();
+ }
}
+ // FIXME: We should leave the prototype scope before parsing the exception
+ // specification, and then reenter it when parsing the trailing return type.
+
+ // Leave prototype scope.
+ PrototypeScope.Exit();
+
// Remember that we parsed a function type, and remember the attributes.
- D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/true, IsVariadic,
+ D.AddTypeInfo(DeclaratorChunk::getFunction(attrs,
+ /*proto*/true, IsVariadic,
EllipsisLoc,
ParamInfo.data(), ParamInfo.size(),
DS.getTypeQualifiers(),
+ RefQualifierIsLValueRef,
+ RefQualifierLoc,
hasExceptionSpec, ThrowLoc,
hasAnyExceptionSpec,
Exceptions.data(),
ExceptionRanges.data(),
Exceptions.size(),
- LParenLoc, RParenLoc, D),
+ LParenLoc, RParenLoc, D,
+ TrailingReturnType),
EndLoc);
}
@@ -3333,10 +3492,12 @@ void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc,
// Remember that we parsed a function type, and remember the attributes. This
// function type is always a K&R style function type, which is not varargs and
// has no prototype.
- D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/false, /*varargs*/false,
+ D.AddTypeInfo(DeclaratorChunk::getFunction(ParsedAttributes(),
+ /*proto*/false, /*varargs*/false,
SourceLocation(),
&ParamInfo[0], ParamInfo.size(),
/*TypeQuals*/0,
+ true, SourceLocation(),
/*exception*/false,
SourceLocation(), false, 0, 0, 0,
LParenLoc, RLoc, D),
@@ -3355,15 +3516,12 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
// This code does a fast path to handle some of the most obvious cases.
if (Tok.getKind() == tok::r_square) {
SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc);
- //FIXME: Use these
- CXX0XAttributeList Attr;
- if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier(true)) {
- Attr = ParseCXX0XAttributes();
- }
+ ParsedAttributes attrs;
+ MaybeParseCXX0XAttributes(attrs);
// Remember that we parsed the empty array type.
ExprResult NumElements;
- D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, 0,
+ D.AddTypeInfo(DeclaratorChunk::getArray(0, attrs, false, false, 0,
StartLoc, EndLoc),
EndLoc);
return;
@@ -3374,18 +3532,12 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
ConsumeToken();
SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc);
- //FIXME: Use these
- CXX0XAttributeList Attr;
- if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
- Attr = ParseCXX0XAttributes();
- }
-
- // If there was an error parsing the assignment-expression, recover.
- if (ExprRes.isInvalid())
- ExprRes.release(); // Deallocate expr, just use [].
+ ParsedAttributes attrs;
+ MaybeParseCXX0XAttributes(attrs);
// Remember that we parsed a array type, and remember its features.
- D.AddTypeInfo(DeclaratorChunk::getArray(0, false, 0, ExprRes.release(),
+ D.AddTypeInfo(DeclaratorChunk::getArray(0, attrs, false, 0,
+ ExprRes.release(),
StartLoc, EndLoc),
EndLoc);
return;
@@ -3446,14 +3598,11 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc);
- //FIXME: Use these
- CXX0XAttributeList Attr;
- if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
- Attr = ParseCXX0XAttributes();
- }
+ ParsedAttributes attrs;
+ MaybeParseCXX0XAttributes(attrs);
// Remember that we parsed a array type, and remember its features.
- D.AddTypeInfo(DeclaratorChunk::getArray(DS.getTypeQualifiers(),
+ D.AddTypeInfo(DeclaratorChunk::getArray(DS.getTypeQualifiers(), attrs,
StaticLoc.isValid(), isStar,
NumElements.release(),
StartLoc, EndLoc),
OpenPOWER on IntegriCloud