diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2011-07-17 15:40:56 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2011-07-17 15:40:56 +0000 |
commit | 180abc3db9ae3b4fc63cd65b15697e6ffcc8a657 (patch) | |
tree | 2097d084eb235c0b12c0bff3445f4ec7bbaa8a12 /lib/Parse/ParseDecl.cpp | |
parent | 29cafa66ad3878dbb9f82615f19fa0bded2e443c (diff) | |
download | src-180abc3db9ae3b4fc63cd65b15697e6ffcc8a657.tar.gz src-180abc3db9ae3b4fc63cd65b15697e6ffcc8a657.zip |
Notes
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] ']' |