[cfe-commits] r152551 - in /cfe/trunk: include/clang/Parse/Parser.h include/clang/Sema/DeclSpec.h lib/Parse/ParseDecl.cpp lib/Parse/ParseDeclCXX.cpp lib/Sema/SemaType.cpp test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p2.cpp test/CXX/dcl.dcl/dc
Richard Smith
richard at metafoo.co.uk
Mon Mar 12 11:08:15 PDT 2012
On Mon, Mar 12, 2012 at 9:24 AM, David Blaikie <dblaikie at gmail.com> wrote:
> On Mon, Mar 12, 2012 at 1:56 AM, Richard Smith
> <richard-llvm at metafoo.co.uk> wrote:
> > Author: rsmith
> > Date: Mon Mar 12 03:56:40 2012
> > New Revision: 152551
> >
> > URL: http://llvm.org/viewvc/llvm-project?rev=152551&view=rev
> > Log:
> > 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').
> >
> > Modified:
> > cfe/trunk/include/clang/Parse/Parser.h
> > cfe/trunk/include/clang/Sema/DeclSpec.h
> > cfe/trunk/lib/Parse/ParseDecl.cpp
> > cfe/trunk/lib/Parse/ParseDeclCXX.cpp
> > cfe/trunk/lib/Sema/SemaType.cpp
> > cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p2.cpp
> > cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
> > cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p9-0x.cpp
> > cfe/trunk/test/Parser/cxx0x-ambig.cpp
> > cfe/trunk/test/Parser/cxx0x-decl.cpp
> > cfe/trunk/test/Parser/cxx0x-lambda-expressions.cpp
> >
> > Modified: cfe/trunk/include/clang/Parse/Parser.h
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=152551&r1=152550&r2=152551&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/include/clang/Parse/Parser.h (original)
> > +++ cfe/trunk/include/clang/Parse/Parser.h Mon Mar 12 03:56:40 2012
> > @@ -1622,6 +1622,7 @@
> > DSC_normal, // normal context
> > DSC_class, // class context, enables 'friend'
> > DSC_type_specifier, // C++ type-specifier-seq
> > + DSC_trailing, // C++11 trailing-type-specifier in a trailing return
> type
> > DSC_top_level // top-level/namespace declaration context
> > };
> >
> >
> > Modified: cfe/trunk/include/clang/Sema/DeclSpec.h
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=152551&r1=152550&r2=152551&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
> > +++ cfe/trunk/include/clang/Sema/DeclSpec.h Mon Mar 12 03:56:40 2012
> > @@ -1428,9 +1428,10 @@
> > ObjCCatchContext, // Objective-C catch exception-declaration
> > BlockLiteralContext, // Block literal declarator.
> > LambdaExprContext, // Lambda-expression declarator.
> > + TrailingReturnContext, // C++11 trailing-type-specifier.
> > TemplateTypeArgContext, // Template type argument.
> > - AliasDeclContext, // C++0x alias-declaration.
> > - AliasTemplateContext // C++0x alias-declaration template.
> > + AliasDeclContext, // C++11 alias-declaration.
> > + AliasTemplateContext // C++11 alias-declaration template.
> > };
> >
> > private:
> > @@ -1604,6 +1605,7 @@
> > case BlockLiteralContext:
> > case LambdaExprContext:
> > case TemplateTypeArgContext:
> > + case TrailingReturnContext:
> > return true;
> > }
> > llvm_unreachable("unknown context kind!");
> > @@ -1635,6 +1637,7 @@
> > case BlockLiteralContext:
> > case LambdaExprContext:
> > case TemplateTypeArgContext:
> > + case TrailingReturnContext:
> > return false;
> > }
> > llvm_unreachable("unknown context kind!");
> > @@ -1679,6 +1682,7 @@
> > case BlockLiteralContext:
> > case LambdaExprContext:
> > case TemplateTypeArgContext:
> > + case TrailingReturnContext:
> > return false;
> > }
> > llvm_unreachable("unknown context kind!");
> >
> > Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=152551&r1=152550&r2=152551&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
> > +++ cfe/trunk/lib/Parse/ParseDecl.cpp Mon Mar 12 03:56:40 2012
> > @@ -36,9 +36,13 @@
> > 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 @@
> > 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 @@
> >
> > // 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 @@
> > 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 @@
> > 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 @@
> > 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());
> >
> > Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=152551&r1=152550&r2=152551&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
> > +++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Mon Mar 12 03:56:40 2012
> > @@ -1114,11 +1114,16 @@
> > if (SuppressingAccessChecks)
> > Actions.ActOnStopSuppressingAccessChecks();
> >
> > - // There are four options here. If we have 'struct foo;', then this
> > - // is either a forward declaration or a friend declaration, which
> > - // have to be treated differently. If we have 'struct foo {...',
> > - // 'struct foo :...' or 'struct foo final[opt]' then this is a
> > - // definition. Otherwise we have something like 'struct foo xyz', a
> reference.
> > + // There are four options here.
> > + // - If we are in a trailing return type, this is always just a
> reference,
> > + // and we must not try to parse a definition. For instance,
> > + // [] () -> struct S { };
> > + // does not define a type.
> > + // - If we have 'struct foo {...', 'struct foo :...',
> > + // 'struct foo final :' or 'struct foo final {', then this is a
> definition.
> > + // - If we have 'struct foo;', then this is either a forward
> declaration
> > + // or a friend declaration, which have to be treated differently.
> > + // - Otherwise we have something like 'struct foo xyz', a reference.
> > // However, in type-specifier-seq's, things look like declarations but
> are
> > // just references, e.g.
> > // new struct s;
> > @@ -1126,10 +1131,12 @@
> > // &T::operator struct s;
> > // For these, DSC is DSC_type_specifier.
> > Sema::TagUseKind TUK;
> > - if (Tok.is(tok::l_brace) ||
> > - (getLangOpts().CPlusPlus && Tok.is(tok::colon)) ||
> > - // FIXME: 'final' must be followed by ':' or '{' to mark a
> definition.
> > - isCXX0XFinalKeyword()) {
> > + if (DSC == DSC_trailing)
> > + TUK = Sema::TUK_Reference;
> > + else if (Tok.is(tok::l_brace) ||
> > + (getLangOpts().CPlusPlus && Tok.is(tok::colon)) ||
> > + (isCXX0XFinalKeyword() &&
> > + NextToken().is(tok::l_brace) ||
> NextToken().is(tok::colon))) {
>
> This caused a -Wlogical-op-parentheses warning which caught a
> crash-on-invalid (perhaps there are valid cases too, but the simple
> case I tested (where the current token is 'foo', not 'final' and is
> followed by a colon) was invalid). I fixed this & included the test
> case in r152559. For completeness we could add a test case for the
> reverse (the case where the brace and colon tests were switched around
> & produced the same sort of bug) but I didn't bother.
Oops, thanks!
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20120312/7a29bbe4/attachment.html>
More information about the cfe-commits
mailing list