aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse/ParseDecl.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-03-12 08:56:40 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-03-12 08:56:40 +0000
commit7796eb5643244f3134834253ce5ea89107ac21c1 (patch)
tree223c93c51604d1e6128470ad42ea5af267b8abaf /lib/Parse/ParseDecl.cpp
parent69730c115c2d0fec2f20609d905d920a5a41b29b (diff)
Fix parsing of trailing-return-type. Types are syntactically prohibited from
being defined here: [] () -> struct S {} does not define struct S. In passing, implement DR1318 (syntactic disambiguation of 'final'). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152551 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/ParseDecl.cpp')
-rw-r--r--lib/Parse/ParseDecl.cpp22
1 files changed, 16 insertions, 6 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index c1f6eb5d42..31a898cf5a 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -36,9 +36,13 @@ TypeResult Parser::ParseTypeName(SourceRange *Range,
Declarator::TheContext Context,
AccessSpecifier AS,
Decl **OwnedType) {
+ DeclSpecContext DSC = DSC_normal;
+ if (Context == Declarator::TrailingReturnContext)
+ DSC = DSC_trailing;
+
// Parse the common declaration-specifiers piece.
DeclSpec DS(AttrFactory);
- ParseSpecifierQualifierList(DS, AS);
+ ParseSpecifierQualifierList(DS, AS, DSC);
if (OwnedType)
*OwnedType = DS.isTypeSpecOwned() ? DS.getRepAsDecl() : 0;
@@ -2653,8 +2657,12 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
while (Tok.is(tok::kw___declspec))
ParseMicrosoftDeclSpec(attrs);
- bool AllowFixedUnderlyingType
- = getLangOpts().CPlusPlus0x || getLangOpts().MicrosoftExt || getLangOpts().ObjC2;
+ // Enum definitions should not be parsed in a trailing-return-type.
+ bool AllowDeclaration = DSC != DSC_trailing;
+
+ bool AllowFixedUnderlyingType = AllowDeclaration &&
+ (getLangOpts().CPlusPlus0x || getLangOpts().MicrosoftExt ||
+ getLangOpts().ObjC2);
CXXScopeSpec &SS = DS.getTypeSpecScope();
if (getLangOpts().CPlusPlus) {
@@ -2679,7 +2687,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
// Must have either 'enum name' or 'enum {...}'.
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::l_brace) &&
- (AllowFixedUnderlyingType && Tok.isNot(tok::colon))) {
+ !(AllowFixedUnderlyingType && Tok.is(tok::colon))) {
Diag(Tok, diag::err_expected_ident_lbrace);
// Skip the rest of this declarator, up until the comma or semicolon.
@@ -2785,6 +2793,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
Sema::TagUseKind TUK;
if (DS.isFriendSpecified())
TUK = Sema::TUK_Friend;
+ else if (!AllowDeclaration)
+ TUK = Sema::TUK_Reference;
else if (Tok.is(tok::l_brace))
TUK = Sema::TUK_Definition;
else if (Tok.is(tok::semi) && DSC != DSC_type_specifier)
@@ -2850,7 +2860,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
if (!TagDecl) {
// The action failed to produce an enumeration tag. If this is a
// definition, consume the entire definition.
- if (Tok.is(tok::l_brace)) {
+ if (Tok.is(tok::l_brace) && TUK != Sema::TUK_Reference) {
ConsumeBrace();
SkipUntil(tok::r_brace);
}
@@ -2859,7 +2869,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
return;
}
- if (Tok.is(tok::l_brace)) {
+ if (Tok.is(tok::l_brace) && TUK != Sema::TUK_Reference) {
if (TUK == Sema::TUK_Friend)
Diag(Tok, diag::err_friend_decl_defines_type)
<< SourceRange(DS.getFriendSpecLoc());