diff options
Diffstat (limited to 'lib/Parse/ParseDecl.cpp')
| -rw-r--r-- | lib/Parse/ParseDecl.cpp | 498 | 
1 files changed, 226 insertions, 272 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index ad3fcfe0d369..0e17295858b9 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -31,10 +31,16 @@ using namespace clang;  ///  /// Called type-id in C++.  TypeResult Parser::ParseTypeName(SourceRange *Range, -                                 Declarator::TheContext Context) { +                                 Declarator::TheContext Context, +                                 ObjCDeclSpec *objcQuals, +                                 AccessSpecifier AS, +                                 Decl **OwnedType) {    // Parse the common declaration-specifiers piece.    DeclSpec DS(AttrFactory); -  ParseSpecifierQualifierList(DS); +  DS.setObjCQualifiers(objcQuals); +  ParseSpecifierQualifierList(DS, AS); +  if (OwnedType) +    *OwnedType = DS.isTypeSpecOwned() ? DS.getRepAsDecl() : 0;    // Parse the abstract-declarator, if present.    Declarator DeclaratorInfo(DS, Context); @@ -672,6 +678,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(StmtVector &Stmts,    ParenBraceBracketBalancer BalancerRAIIObj(*this);    Decl *SingleDecl = 0; +  Decl *OwnedType = 0;    switch (Tok.getKind()) {    case tok::kw_template:    case tok::kw_export: @@ -694,7 +701,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(StmtVector &Stmts,      break;    case tok::kw_using:      SingleDecl = ParseUsingDirectiveOrDeclaration(Context, ParsedTemplateInfo(), -                                                  DeclEnd, attrs); +                                                  DeclEnd, attrs, &OwnedType);      break;    case tok::kw_static_assert:    case tok::kw__Static_assert: @@ -706,8 +713,9 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(StmtVector &Stmts,    }    // This routine returns a DeclGroup, if the thing we parsed only contains a -  // single decl, convert it now. -  return Actions.ConvertDeclToDeclGroup(SingleDecl); +  // single decl, convert it now. Alias declarations can also declare a type; +  // include that too if it is present. +  return Actions.ConvertDeclToDeclGroup(SingleDecl, OwnedType);  }  ///       simple-declaration: [C99 6.7: declaration] [C++ 7p1: dcl.dcl] @@ -1079,10 +1087,10 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D,  ///          type-qualifier specifier-qualifier-list[opt]  /// [GNU]    attributes     specifier-qualifier-list[opt]  /// -void Parser::ParseSpecifierQualifierList(DeclSpec &DS) { +void Parser::ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS) {    /// specifier-qualifier-list is a subset of declaration-specifiers.  Just    /// parse declaration-specifiers and complain about extra stuff. -  ParseDeclarationSpecifiers(DS); +  ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS);    // Validate declspec for type-name.    unsigned Specs = DS.getParsedSpecifiers(); @@ -1394,8 +1402,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,          // Thus, if the template-name is actually the constructor          // name, then the code is ill-formed; this interpretation is          // reinforced by the NAD status of core issue 635.  -        TemplateIdAnnotation *TemplateId -          = static_cast<TemplateIdAnnotation *>(Next.getAnnotationValue()); +        TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Next);          if ((DSContext == DSC_top_level ||               (DSContext == DSC_class && DS.isFriendSpecified())) &&              TemplateId->Name && @@ -1597,8 +1604,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,        // type-name      case tok::annot_template_id: { -      TemplateIdAnnotation *TemplateId -        = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue()); +      TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);        if (TemplateId->Kind != TNK_Type_template) {          // This template-id does not refer to a type name, so we're          // done with the type-specifiers. @@ -2444,13 +2450,29 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,      Actions.CodeCompleteTag(getCurScope(), DeclSpec::TST_enum);      ConsumeCodeCompletionToken();    } + +  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(); +  }    // If attributes exist after tag, parse them.    ParsedAttributes attrs(AttrFactory);    MaybeParseGNUAttributes(attrs); +  bool AllowFixedUnderlyingType = getLang().CPlusPlus0x || getLang().Microsoft; +    CXXScopeSpec &SS = DS.getTypeSpecScope();    if (getLang().CPlusPlus) { +    // "enum foo : bar;" is not a potential typo for "enum foo::bar;" +    // if a fixed underlying type is allowed. +    ColonProtectionRAIIObject X(*this, AllowFixedUnderlyingType); +          if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false))        return; @@ -2465,17 +2487,6 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,      }    } -  bool AllowFixedUnderlyingType = getLang().CPlusPlus0x || getLang().Microsoft; -  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) &&        (AllowFixedUnderlyingType && Tok.isNot(tok::colon))) { @@ -3016,6 +3027,10 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {    case tok::kw___attribute:      return true; +    // C++0x decltype. +  case tok::kw_decltype: +    return true; +      // GNU ObjC bizarre protocol extension: <proto1,proto2> with implicit 'id'.    case tok::less:      return getLang().ObjC1; @@ -3639,33 +3654,15 @@ void Parser::ParseParenDeclarator(Declarator &D) {  /// declarator D up to a paren, which indicates that we are parsing function  /// arguments.  /// -/// If AttrList is non-null, then the caller parsed those arguments immediately +/// If attrs is non-null, then the caller parsed those arguments immediately  /// after the open paren - they should be considered to be the first argument of  /// a parameter.  If RequiresArg is true, then the first argument of the  /// function is required to be present and required to not be an identifier  /// list.  /// -/// This method also handles this portion of the grammar: -///       parameter-type-list: [C99 6.7.5] -///         parameter-list -///         parameter-list ',' '...' -/// [C++]   parameter-list '...' -/// -///       parameter-list: [C99 6.7.5] -///         parameter-declaration -///         parameter-list ',' parameter-declaration -/// -///       parameter-declaration: [C99 6.7.5] -///         declaration-specifiers declarator -/// [C++]   declaration-specifiers declarator '=' assignment-expression -/// [GNU]   declaration-specifiers declarator attributes -///         declaration-specifiers abstract-declarator[opt] -/// [C++]   declaration-specifiers abstract-declarator[opt] -///           '=' assignment-expression -/// [GNU]   declaration-specifiers abstract-declarator[opt] attributes -/// -/// For C++, after the parameter-list, it also parses "cv-qualifier-seq[opt]", -/// C++0x "ref-qualifier[opt]" and "exception-specification[opt]". +/// For C++, after the parameter-list, it also parses cv-qualifier-seq[opt], +/// (C++0x) ref-qualifier[opt], exception-specification[opt], and +/// (C++0x) trailing-return-type[opt].  ///  /// [C++0x] exception-specification:  ///           dynamic-exception-specification @@ -3677,36 +3674,62 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,    // lparen is already consumed!    assert(D.isPastIdentifier() && "Should not call before identifier!"); +  // This should be true when the function has typed arguments. +  // Otherwise, it is treated as a K&R-style function. +  bool HasProto = false; +  // Build up an array of information about the parsed arguments. +  llvm::SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo; +  // Remember where we see an ellipsis, if any. +  SourceLocation EllipsisLoc; + +  DeclSpec DS(AttrFactory); +  bool RefQualifierIsLValueRef = true; +  SourceLocation RefQualifierLoc; +  ExceptionSpecificationType ESpecType = EST_None; +  SourceRange ESpecRange; +  llvm::SmallVector<ParsedType, 2> DynamicExceptions; +  llvm::SmallVector<SourceRange, 2> DynamicExceptionRanges; +  ExprResult NoexceptExpr;    ParsedType TrailingReturnType; +   +  SourceLocation EndLoc; -  // This parameter list may be empty. -  if (Tok.is(tok::r_paren)) { +  if (isFunctionDeclaratorIdentifierList()) {      if (RequiresArg)        Diag(Tok, diag::err_argument_required_after_attribute); -    SourceLocation EndLoc = ConsumeParen();  // Eat the closing ')'. +    ParseFunctionDeclaratorIdentifierList(D, ParamInfo); + +    EndLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); +  } else { +    // Enter function-declaration scope, limiting any declarators to the +    // function prototype scope, including parameter declarators. +    ParseScope PrototypeScope(this, +                              Scope::FunctionPrototypeScope|Scope::DeclScope); + +    if (Tok.isNot(tok::r_paren)) +      ParseParameterDeclarationClause(D, attrs, ParamInfo, EllipsisLoc); +    else if (RequiresArg) +      Diag(Tok, diag::err_argument_required_after_attribute); + +    HasProto = ParamInfo.size() || getLang().CPlusPlus; + +    // If we have the closing ')', eat it. +    EndLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); -    // cv-qualifier-seq[opt]. -    DeclSpec DS(AttrFactory); -    SourceLocation RefQualifierLoc; -    bool RefQualifierIsLValueRef = true; -    ExceptionSpecificationType ESpecType = EST_None; -    SourceRange ESpecRange; -    llvm::SmallVector<ParsedType, 2> DynamicExceptions; -    llvm::SmallVector<SourceRange, 2> DynamicExceptionRanges; -    ExprResult NoexceptExpr;      if (getLang().CPlusPlus) {        MaybeParseCXX0XAttributes(attrs); +      // Parse cv-qualifier-seq[opt].        ParseTypeQualifierListOpt(DS, false /*no attributes*/); -      if (!DS.getSourceRange().getEnd().isInvalid()) -        EndLoc = DS.getSourceRange().getEnd(); +        if (!DS.getSourceRange().getEnd().isInvalid()) +          EndLoc = DS.getSourceRange().getEnd(); -      // Parse ref-qualifier[opt] +      // 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; @@ -3720,87 +3743,158 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,        if (ESpecType != EST_None)          EndLoc = ESpecRange.getEnd(); -      // Parse trailing-return-type. +      // Parse trailing-return-type[opt].        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, -                                               /*variadic*/ false, -                                               SourceLocation(), -                                               /*arglist*/ 0, 0, -                                               DS.getTypeQualifiers(), -                                               RefQualifierIsLValueRef, -                                               RefQualifierLoc, -                                               ESpecType, ESpecRange.getBegin(), -                                               DynamicExceptions.data(), -                                               DynamicExceptionRanges.data(), -                                               DynamicExceptions.size(), -                                               NoexceptExpr.isUsable() ? -                                                 NoexceptExpr.get() : 0, -                                               LParenLoc, EndLoc, D, -                                               TrailingReturnType), -                  attrs, EndLoc); -    return; +    // Leave prototype scope. +    PrototypeScope.Exit();    } -  // Alternatively, this parameter list may be an identifier list form for a -  // K&R-style function:  void foo(a,b,c) -  if (!getLang().CPlusPlus && Tok.is(tok::identifier) -      && !TryAltiVecVectorToken()) { -    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) -        Diag(Tok, diag::err_argument_required_after_attribute); -       -      // Identifier list.  Note that '(' identifier-list ')' is only allowed for -      // 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; +  // Remember that we parsed a function type, and remember the attributes. +  D.AddTypeInfo(DeclaratorChunk::getFunction(HasProto, +                                             /*isVariadic=*/EllipsisLoc.isValid(), +                                             EllipsisLoc, +                                             ParamInfo.data(), ParamInfo.size(), +                                             DS.getTypeQualifiers(), +                                             RefQualifierIsLValueRef, +                                             RefQualifierLoc, +                                             /*MutableLoc=*/SourceLocation(), +                                             ESpecType, ESpecRange.getBegin(), +                                             DynamicExceptions.data(), +                                             DynamicExceptionRanges.data(), +                                             DynamicExceptions.size(), +                                             NoexceptExpr.isUsable() ? +                                               NoexceptExpr.get() : 0, +                                             LParenLoc, EndLoc, D, +                                             TrailingReturnType), +                attrs, EndLoc); +} + +/// isFunctionDeclaratorIdentifierList - This parameter list may have an +/// identifier list form for a K&R-style function:  void foo(a,b,c) +/// +/// Note that identifier-lists are only allowed for normal declarators, not for +/// abstract-declarators. +bool Parser::isFunctionDeclaratorIdentifierList() { +  return !getLang().CPlusPlus +         && Tok.is(tok::identifier) +         && !TryAltiVecVectorToken() +         // K&R identifier lists can't have typedefs as identifiers, per C99 +         // 6.7.5.3p11. +         && (TryAnnotateTypeOrScopeToken() || !Tok.is(tok::annot_typename)) +         // Identifier lists follow a really simple grammar: the identifiers can +         // be followed *only* by a ", identifier" 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 then do we parse it as an +         // identifier list. +         && (NextToken().is(tok::comma) || NextToken().is(tok::r_paren)); +} + +/// ParseFunctionDeclaratorIdentifierList - While parsing a function declarator +/// we found a K&R-style identifier list instead of a typed parameter list. +/// +/// After returning, ParamInfo will hold the parsed parameters. +/// +///       identifier-list: [C99 6.7.5] +///         identifier +///         identifier-list ',' identifier +/// +void Parser::ParseFunctionDeclaratorIdentifierList( +       Declarator &D, +       llvm::SmallVector<DeclaratorChunk::ParamInfo, 16> &ParamInfo) { +  // If there was no identifier specified for the declarator, either we are in +  // an abstract-declarator, or we are in a parameter declarator which was found +  // to be abstract.  In abstract-declarators, identifier lists are not valid: +  // diagnose this. +  if (!D.getIdentifier()) +    Diag(Tok, diag::ext_ident_list_in_param); + +  // Maintain an efficient lookup of params we have seen so far. +  llvm::SmallSet<const IdentifierInfo*, 16> ParamsSoFar; + +  while (1) { +    // If this isn't an identifier, report the error and skip until ')'. +    if (Tok.isNot(tok::identifier)) { +      Diag(Tok, diag::err_expected_ident); +      SkipUntil(tok::r_paren, /*StopAtSemi=*/true, /*DontConsume=*/true); +      // Forget we parsed anything. +      ParamInfo.clear(); +      return;      } -  } -  // Finally, a normal, non-empty parameter type list. +    IdentifierInfo *ParmII = Tok.getIdentifierInfo(); -  // Build up an array of information about the parsed arguments. -  llvm::SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo; +    // Reject 'typedef int y; int test(x, y)', but continue parsing. +    if (Actions.getTypeName(*ParmII, Tok.getLocation(), getCurScope())) +      Diag(Tok, diag::err_unexpected_typedef_ident) << ParmII; + +    // Verify that the argument identifier has not already been mentioned. +    if (!ParamsSoFar.insert(ParmII)) { +      Diag(Tok, diag::err_param_redefinition) << ParmII; +    } else { +      // Remember this identifier in ParamInfo. +      ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII, +                                                     Tok.getLocation(), +                                                     0)); +    } + +    // Eat the identifier. +    ConsumeToken(); -  // Enter function-declaration scope, limiting any declarators to the -  // function prototype scope, including parameter declarators. -  ParseScope PrototypeScope(this, -                            Scope::FunctionPrototypeScope|Scope::DeclScope); +    // The list continues if we see a comma. +    if (Tok.isNot(tok::comma)) +      break; +    ConsumeToken(); +  } +} + +/// ParseParameterDeclarationClause - Parse a (possibly empty) parameter-list +/// after the opening parenthesis. This function will not parse a K&R-style +/// identifier list. +/// +/// D is the declarator being parsed.  If attrs is non-null, then the caller +/// parsed those arguments immediately after the open paren - they should be +/// considered to be the first argument of a parameter. +/// +/// After returning, ParamInfo will hold the parsed parameters. EllipsisLoc will +/// be the location of the ellipsis, if any was parsed. +/// +///       parameter-type-list: [C99 6.7.5] +///         parameter-list +///         parameter-list ',' '...' +/// [C++]   parameter-list '...' +/// +///       parameter-list: [C99 6.7.5] +///         parameter-declaration +///         parameter-list ',' parameter-declaration +/// +///       parameter-declaration: [C99 6.7.5] +///         declaration-specifiers declarator +/// [C++]   declaration-specifiers declarator '=' assignment-expression +/// [GNU]   declaration-specifiers declarator attributes +///         declaration-specifiers abstract-declarator[opt] +/// [C++]   declaration-specifiers abstract-declarator[opt] +///           '=' assignment-expression +/// [GNU]   declaration-specifiers abstract-declarator[opt] attributes +/// +void Parser::ParseParameterDeclarationClause( +       Declarator &D, +       ParsedAttributes &attrs, +       llvm::SmallVector<DeclaratorChunk::ParamInfo, 16> &ParamInfo, +       SourceLocation &EllipsisLoc) { -  bool IsVariadic = false; -  SourceLocation EllipsisLoc;    while (1) {      if (Tok.is(tok::ellipsis)) { -      IsVariadic = true;        EllipsisLoc = ConsumeToken();     // Consume the ellipsis.        break;      } @@ -3817,6 +3911,11 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,      // If the caller parsed attributes for the first argument, add them now.      // Take them so that we only apply the attributes to the first parameter. +    // FIXME: If we saw an ellipsis first, this code is not reached. Are the +    // attributes lost? Should they even be allowed? +    // FIXME: If we can leave the attributes in the token stream somehow, we can +    // get rid of a parameter (attrs) and this statement. It might be too much +    // hassle.      DS.takeAttributesFrom(attrs);      ParseDeclarationSpecifiers(DS); @@ -3912,7 +4011,6 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,      // If the next token is a comma, consume it and keep reading arguments.      if (Tok.isNot(tok::comma)) {        if (Tok.is(tok::ellipsis)) { -        IsVariadic = true;          EllipsisLoc = ConsumeToken();     // Consume the ellipsis.          if (!getLang().CPlusPlus) { @@ -3930,150 +4028,6 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,      ConsumeToken();    } -  // If we have the closing ')', eat it. -  SourceLocation EndLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); - -  DeclSpec DS(AttrFactory); -  SourceLocation RefQualifierLoc; -  bool RefQualifierIsLValueRef = true; -  ExceptionSpecificationType ESpecType = EST_None; -  SourceRange ESpecRange; -  llvm::SmallVector<ParsedType, 2> DynamicExceptions; -  llvm::SmallVector<SourceRange, 2> DynamicExceptionRanges; -  ExprResult NoexceptExpr; -   -  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; -    } - -    // FIXME: We should leave the prototype scope before parsing the exception -    // specification, and then reenter it when parsing the trailing return type. -    // FIXMEFIXME: Why? That wouldn't be right for the noexcept clause. - -    // Parse exception-specification[opt]. -    ESpecType = MaybeParseExceptionSpecification(ESpecRange, -                                                 DynamicExceptions, -                                                 DynamicExceptionRanges, -                                                 NoexceptExpr); -    if (ESpecType != EST_None) -      EndLoc = ESpecRange.getEnd(); - -    // Parse trailing-return-type. -    if (getLang().CPlusPlus0x && Tok.is(tok::arrow)) { -      TrailingReturnType = ParseTrailingReturnType().get(); -    } -  } - -  // Leave prototype scope. -  PrototypeScope.Exit(); - -  // Remember that we parsed a function type, and remember the attributes. -  D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/true, IsVariadic, -                                             EllipsisLoc, -                                             ParamInfo.data(), ParamInfo.size(), -                                             DS.getTypeQualifiers(), -                                             RefQualifierIsLValueRef, -                                             RefQualifierLoc, -                                             ESpecType, ESpecRange.getBegin(), -                                             DynamicExceptions.data(), -                                             DynamicExceptionRanges.data(), -                                             DynamicExceptions.size(), -                                             NoexceptExpr.isUsable() ? -                                               NoexceptExpr.get() : 0, -                                             LParenLoc, EndLoc, D, -                                             TrailingReturnType), -                attrs, EndLoc); -} - -/// ParseFunctionDeclaratorIdentifierList - While parsing a function declarator -/// we found a K&R-style identifier list instead of a type argument list.  The -/// 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; -  llvm::SmallSet<const IdentifierInfo*, 16> ParamsSoFar; - -  // If there was no identifier specified for the declarator, either we are in -  // an abstract-declarator, or we are in a parameter declarator which was found -  // to be abstract.  In abstract-declarators, identifier lists are not valid: -  // diagnose this. -  if (!D.getIdentifier()) -    Diag(FirstIdentLoc, diag::ext_ident_list_in_param); - -  // 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, 0)); - -  while (Tok.is(tok::comma)) { -    // Eat the comma. -    ConsumeToken(); - -    // If this isn't an identifier, report the error and skip until ')'. -    if (Tok.isNot(tok::identifier)) { -      Diag(Tok, diag::err_expected_ident); -      SkipUntil(tok::r_paren); -      return; -    } - -    IdentifierInfo *ParmII = Tok.getIdentifierInfo(); - -    // Reject 'typedef int y; int test(x, y)', but continue parsing. -    if (Actions.getTypeName(*ParmII, Tok.getLocation(), getCurScope())) -      Diag(Tok, diag::err_unexpected_typedef_ident) << ParmII; - -    // Verify that the argument identifier has not already been mentioned. -    if (!ParamsSoFar.insert(ParmII)) { -      Diag(Tok, diag::err_param_redefinition) << ParmII; -    } else { -      // Remember this identifier in ParamInfo. -      ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII, -                                                     Tok.getLocation(), -                                                     0)); -    } - -    // Eat the identifier. -    ConsumeToken(); -  } - -  // If we have the closing ')', eat it and we're done. -  SourceLocation RLoc = MatchRHSPunctuation(tok::r_paren, 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. -  ParsedAttributes attrs(AttrFactory); -  D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/false, /*varargs*/false, -                                             SourceLocation(), -                                             &ParamInfo[0], ParamInfo.size(), -                                             /*TypeQuals*/0, -                                             true, SourceLocation(), -                                             EST_None, SourceLocation(), 0, 0, -                                             0, 0, LParenLoc, RLoc, D), -                attrs, RLoc);  }  /// [C90]   direct-declarator '[' constant-expression[opt] ']'  | 
