[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