diff options
| author | Roman Divacky <rdivacky@FreeBSD.org> | 2010-01-15 15:39:40 +0000 |
|---|---|---|
| committer | Roman Divacky <rdivacky@FreeBSD.org> | 2010-01-15 15:39:40 +0000 |
| commit | ee791dde723a2089c681d2ab6a9d4f96379d5f49 (patch) | |
| tree | a6082d4d1d1e9ddaea09a6a04bb4a47da95d642d /lib/Parse | |
| parent | abe15e553e58165e7692c0d0842865c488ed7b45 (diff) | |
Notes
Diffstat (limited to 'lib/Parse')
| -rw-r--r-- | lib/Parse/DeclSpec.cpp | 8 | ||||
| -rw-r--r-- | lib/Parse/ParseDecl.cpp | 178 | ||||
| -rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 58 | ||||
| -rw-r--r-- | lib/Parse/ParseExpr.cpp | 24 | ||||
| -rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 52 | ||||
| -rw-r--r-- | lib/Parse/ParseObjc.cpp | 39 | ||||
| -rw-r--r-- | lib/Parse/ParseStmt.cpp | 8 | ||||
| -rw-r--r-- | lib/Parse/ParseTemplate.cpp | 3 | ||||
| -rw-r--r-- | lib/Parse/Parser.cpp | 6 |
9 files changed, 321 insertions, 55 deletions
diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp index 4cd8fe887bb1..f52d8b98567a 100644 --- a/lib/Parse/DeclSpec.cpp +++ b/lib/Parse/DeclSpec.cpp @@ -36,6 +36,14 @@ void UnqualifiedId::setTemplateId(TemplateIdAnnotation *TemplateId) { EndLocation = TemplateId->RAngleLoc; } +void UnqualifiedId::setConstructorTemplateId(TemplateIdAnnotation *TemplateId) { + assert(TemplateId && "NULL template-id annotation?"); + Kind = IK_ConstructorTemplateId; + this->TemplateId = TemplateId; + StartLocation = TemplateId->TemplateNameLoc; + EndLocation = TemplateId->RAngleLoc; +} + /// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function. /// "TheDeclarator" is the declarator that this will be added to. DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic, diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index f429ac991d83..b5ba8acafc8d 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -356,7 +356,8 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context, ParsingDeclSpec DS(*this); if (Attr) DS.AddAttributes(Attr); - ParseDeclarationSpecifiers(DS); + ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none, + getDeclSpecContextFromDeclaratorContext(Context)); // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };" // declaration-specifiers init-declarator-list[opt] ';' @@ -786,6 +787,20 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, return false; } +/// \brief Determine the declaration specifier context from the declarator +/// context. +/// +/// \param Context the declarator context, which is one of the +/// Declarator::TheContext enumerator values. +Parser::DeclSpecContext +Parser::getDeclSpecContextFromDeclaratorContext(unsigned Context) { + if (Context == Declarator::MemberContext) + return DSC_class; + if (Context == Declarator::FileContext) + return DSC_top_level; + return DSC_normal; +} + /// ParseDeclarationSpecifiers /// declaration-specifiers: [C99 6.7] /// storage-class-specifier declaration-specifiers[opt] @@ -814,7 +829,16 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, AccessSpecifier AS, DeclSpecContext DSContext) { if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteOrdinaryName(CurScope); + Action::CodeCompletionContext CCC = Action::CCC_Namespace; + if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) + CCC = DSContext == DSC_class? Action::CCC_MemberTemplate + : Action::CCC_Template; + else if (DSContext == DSC_class) + CCC = Action::CCC_Class; + else if (ObjCImpDecl) + CCC = Action::CCC_ObjCImplementation; + + Actions.CodeCompleteOrdinaryName(CurScope, CCC); ConsumeToken(); } @@ -854,6 +878,47 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, static_cast<TemplateIdAnnotation *>(Next.getAnnotationValue()) ->Kind == TNK_Type_template) { // We have a qualified template-id, e.g., N::A<int> + + // C++ [class.qual]p2: + // In a lookup in which the constructor is an acceptable lookup + // result and the nested-name-specifier nominates a class C: + // + // - if the name specified after the + // nested-name-specifier, when looked up in C, is the + // injected-class-name of C (Clause 9), or + // + // - if the name specified after the nested-name-specifier + // is the same as the identifier or the + // simple-template-id's template-name in the last + // component of the nested-name-specifier, + // + // the name is instead considered to name the constructor of + // class C. + // + // 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()); + if (DSContext == DSC_top_level && TemplateId->Name && + Actions.isCurrentClassName(*TemplateId->Name, CurScope, &SS)) { + if (isConstructorDeclarator()) { + // The user meant this to be an out-of-line constructor + // definition, but template arguments are not allowed + // there. Just allow this as a constructor; we'll + // complain about it later. + goto DoneWithDeclSpec; + } + + // The user meant this to name a type, but it actually names + // a constructor with some extraneous template + // arguments. Complain, then parse it as a type as the user + // intended. + Diag(TemplateId->TemplateNameLoc, + diag::err_out_of_line_template_id_names_constructor) + << TemplateId->Name; + } + DS.getTypeSpecScope() = SS; ConsumeToken(); // The C++ scope. assert(Tok.is(tok::annot_template_id) && @@ -878,13 +943,23 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, if (Next.isNot(tok::identifier)) goto DoneWithDeclSpec; - // If the next token is the name of the class type that the C++ scope - // denotes, followed by a '(', then this is a constructor declaration. - // We're done with the decl-specifiers. - if (Actions.isCurrentClassName(*Next.getIdentifierInfo(), - CurScope, &SS) && - GetLookAheadToken(2).is(tok::l_paren)) - goto DoneWithDeclSpec; + // If we're in a context where the identifier could be a class name, + // check whether this is a constructor declaration. + if (DSContext == DSC_top_level && + Actions.isCurrentClassName(*Next.getIdentifierInfo(), CurScope, + &SS)) { + if (isConstructorDeclarator()) + goto DoneWithDeclSpec; + + // As noted in C++ [class.qual]p2 (cited above), when the name + // of the class is qualified in a context where it could name + // a constructor, its a constructor name. However, we've + // looked at the declarator, and the user probably meant this + // to be a type. Complain that it isn't supposed to be treated + // as a type, then proceed to parse it as a type. + Diag(Next.getLocation(), diag::err_out_of_line_type_names_constructor) + << Next.getIdentifierInfo(); + } TypeTy *TypeRep = Actions.getTypeName(*Next.getIdentifierInfo(), Next.getLocation(), CurScope, &SS); @@ -965,16 +1040,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, goto DoneWithDeclSpec; } - // C++: If the identifier is actually the name of the class type - // being defined and the next token is a '(', then this is a - // constructor declaration. We're done with the decl-specifiers - // and will treat this token as an identifier. - if (getLang().CPlusPlus && - (CurScope->isClassScope() || - (CurScope->isTemplateParamScope() && - CurScope->getParent()->isClassScope())) && + // If we're in a context where the identifier could be a class name, + // check whether this is a constructor declaration. + if (getLang().CPlusPlus && DSContext == DSC_class && Actions.isCurrentClassName(*Tok.getIdentifierInfo(), CurScope) && - NextToken().getKind() == tok::l_paren) + isConstructorDeclarator()) goto DoneWithDeclSpec; isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, @@ -1017,6 +1087,14 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, goto DoneWithDeclSpec; } + // If we're in a context where the template-id could be a + // constructor name or specialization, check whether this is a + // constructor declaration. + if (getLang().CPlusPlus && DSContext == DSC_class && + Actions.isCurrentClassName(*TemplateId->Name, CurScope) && + isConstructorDeclarator()) + goto DoneWithDeclSpec; + // Turn the template-id annotation token into a type annotation // token, then try again to parse it as a type-specifier. AnnotateTemplateIdTokenAsType(); @@ -2082,6 +2160,48 @@ bool Parser::isDeclarationSpecifier() { } } +bool Parser::isConstructorDeclarator() { + TentativeParsingAction TPA(*this); + + // Parse the C++ scope specifier. + CXXScopeSpec SS; + ParseOptionalCXXScopeSpecifier(SS, 0, true); + + // Parse the constructor name. + if (Tok.is(tok::identifier) || Tok.is(tok::annot_template_id)) { + // We already know that we have a constructor name; just consume + // the token. + ConsumeToken(); + } else { + TPA.Revert(); + return false; + } + + // Current class name must be followed by a left parentheses. + if (Tok.isNot(tok::l_paren)) { + TPA.Revert(); + return false; + } + ConsumeParen(); + + // A right parentheses or ellipsis signals that we have a constructor. + if (Tok.is(tok::r_paren) || Tok.is(tok::ellipsis)) { + TPA.Revert(); + return true; + } + + // If we need to, enter the specified scope. + DeclaratorScopeObj DeclScopeObj(*this, SS); + if (SS.isSet() && Actions.ShouldEnterDeclaratorScope(CurScope, SS)) + DeclScopeObj.EnterDeclaratorScope(); + + // Check whether the next token(s) are part of a declaration + // specifier, in which case we have the start of a parameter and, + // therefore, we know that this is a constructor. + bool IsConstructor = isDeclarationSpecifier(); + TPA.Revert(); + return IsConstructor; +} /// ParseTypeQualifierListOpt /// type-qualifier-list: [C99 6.7.5] @@ -2366,10 +2486,16 @@ void Parser::ParseDirectDeclarator(Declarator &D) { Tok.is(tok::annot_template_id) || Tok.is(tok::tilde)) { // We found something that indicates the start of an unqualified-id. // Parse that unqualified-id. + bool AllowConstructorName + = ((D.getCXXScopeSpec().isSet() && + D.getContext() == Declarator::FileContext) || + (!D.getCXXScopeSpec().isSet() && + D.getContext() == Declarator::MemberContext)) && + !D.getDeclSpec().hasTypeSpecifier(); if (ParseUnqualifiedId(D.getCXXScopeSpec(), /*EnteringContext=*/true, /*AllowDestructorName=*/true, - /*AllowConstructorName=*/!D.getDeclSpec().hasTypeSpecifier(), + AllowConstructorName, /*ObjectType=*/0, D.getName())) { D.SetIdentifier(0, Tok.getLocation()); @@ -2396,6 +2522,16 @@ void Parser::ParseDirectDeclarator(Declarator &D) { // direct-declarator: '(' attributes declarator ')' // Example: 'char (*X)' or 'int (*XX)(void)' ParseParenDeclarator(D); + + // If the declarator was parenthesized, we entered the declarator + // scope when parsing the parenthesized declarator, then exited + // the scope already. Re-enter the scope, if we need to. + if (D.getCXXScopeSpec().isSet()) { + if (Actions.ShouldEnterDeclaratorScope(CurScope, D.getCXXScopeSpec())) + // Change the declaration context for name lookup, until this function + // is exited (and the declarator has been parsed). + DeclScopeObj.EnterDeclaratorScope(); + } } else if (D.mayOmitIdentifier()) { // This could be something simple like "int" (in which case the declarator // portion is empty), if an abstract-declarator is allowed. @@ -3020,6 +3156,8 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) { Token OpTok = Tok; SourceLocation StartLoc = ConsumeToken(); + const bool hasParens = Tok.is(tok::l_paren); + bool isCastExpr; TypeTy *CastTy; SourceRange CastRange; @@ -3027,6 +3165,8 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) { isCastExpr, CastTy, CastRange); + if (hasParens) + DS.setTypeofParensRange(CastRange); if (CastRange.getEnd().isInvalid()) // FIXME: Not accurate, the range gets one token more than it should. diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 265d0f3e849f..90040c54bfb1 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -468,7 +468,8 @@ Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation, if (Tok.is(tok::annot_template_id)) { TemplateIdAnnotation *TemplateId = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue()); - if (TemplateId->Kind == TNK_Type_template) { + if (TemplateId->Kind == TNK_Type_template || + TemplateId->Kind == TNK_Dependent_template_name) { AnnotateTemplateIdTokenAsType(SS); assert(Tok.is(tok::annot_typename) && "template-id -> type failed"); @@ -489,18 +490,57 @@ Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation, return true; } + IdentifierInfo *Id = Tok.getIdentifierInfo(); + SourceLocation IdLoc = ConsumeToken(); + + if (Tok.is(tok::less)) { + // It looks the user intended to write a template-id here, but the + // template-name was wrong. Try to fix that. + TemplateNameKind TNK = TNK_Type_template; + TemplateTy Template; + if (!Actions.DiagnoseUnknownTemplateName(*Id, IdLoc, CurScope, + SS, Template, TNK)) { + Diag(IdLoc, diag::err_unknown_template_name) + << Id; + } + + if (!Template) + return true; + + // Form the template name + UnqualifiedId TemplateName; + TemplateName.setIdentifier(Id, IdLoc); + + // Parse the full template-id, then turn it into a type. + if (AnnotateTemplateIdToken(Template, TNK, SS, TemplateName, + SourceLocation(), true)) + return true; + if (TNK == TNK_Dependent_template_name) + AnnotateTemplateIdTokenAsType(SS); + + // If we didn't end up with a typename token, there's nothing more we + // can do. + if (Tok.isNot(tok::annot_typename)) + return true; + + // Retrieve the type from the annotation token, consume that token, and + // return. + EndLocation = Tok.getAnnotationEndLoc(); + TypeTy *Type = Tok.getAnnotationValue(); + ConsumeToken(); + return Type; + } + // We have an identifier; check whether it is actually a type. - TypeTy *Type = Actions.getTypeName(*Tok.getIdentifierInfo(), - Tok.getLocation(), CurScope, SS, - true); - if (!Type) { - Diag(Tok, DestrExpected ? diag::err_destructor_class_name + TypeTy *Type = Actions.getTypeName(*Id, IdLoc, CurScope, SS, true); + if (!Type) { + Diag(IdLoc, DestrExpected ? diag::err_destructor_class_name : diag::err_expected_class_name); return true; } // Consume the identifier. - EndLocation = ConsumeToken(); + EndLocation = IdLoc; return Type; } @@ -1527,12 +1567,12 @@ Parser::MemInitResult Parser::ParseMemInitializer(DeclPtrTy ConstructorDecl) { if (Tok.is(tok::annot_template_id)) { TemplateIdAnnotation *TemplateId = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue()); - if (TemplateId->Kind == TNK_Type_template) { + if (TemplateId->Kind == TNK_Type_template || + TemplateId->Kind == TNK_Dependent_template_name) { AnnotateTemplateIdTokenAsType(&SS); assert(Tok.is(tok::annot_typename) && "template-id -> type failed"); TemplateTypeTy = Tok.getAnnotationValue(); } - // FIXME. May need to check for TNK_Dependent_template as well. } if (!TemplateTypeTy && Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected_member_or_base_name); diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index bdbc67f782dc..669575c4f030 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -200,11 +200,6 @@ static prec::Level getBinOpPrecedence(tok::TokenKind Kind, /// expression ',' assignment-expression /// Parser::OwningExprResult Parser::ParseExpression() { - if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteOrdinaryName(CurScope); - ConsumeToken(); - } - OwningExprResult LHS(ParseAssignmentExpression()); if (LHS.isInvalid()) return move(LHS); @@ -248,6 +243,11 @@ Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) { /// ParseAssignmentExpression - Parse an expr that doesn't include commas. /// Parser::OwningExprResult Parser::ParseAssignmentExpression() { + if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Expression); + ConsumeToken(); + } + if (Tok.is(tok::kw_throw)) return ParseThrowExpression(); @@ -616,9 +616,17 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression, // Turn a potentially qualified name into a annot_typename or // annot_cxxscope if it would be valid. This handles things like x::y, etc. if (getLang().CPlusPlus) { - // If TryAnnotateTypeOrScopeToken annotates the token, tail recurse. - if (TryAnnotateTypeOrScopeToken()) - return ParseCastExpression(isUnaryExpression, isAddressOfOperand); + // Avoid the unnecessary parse-time lookup in the common case + // where the syntax forbids a type. + const Token &Next = NextToken(); + if (Next.is(tok::coloncolon) || + (!ColonIsSacred && Next.is(tok::colon)) || + Next.is(tok::less) || + Next.is(tok::l_paren)) { + // If TryAnnotateTypeOrScopeToken annotates the token, tail recurse. + if (TryAnnotateTypeOrScopeToken()) + return ParseCastExpression(isUnaryExpression, isAddressOfOperand); + } } // Consume the identifier so that we can see if it is followed by a '(' or diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index abd26d7d4905..ca50ef400092 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -585,6 +585,11 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { /// \returns true if there was a parsing, false otherwise. bool Parser::ParseCXXCondition(OwningExprResult &ExprResult, DeclPtrTy &DeclResult) { + if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Condition); + ConsumeToken(); + } + if (!isCXXConditionDeclaration()) { ExprResult = ParseExpression(); // expression DeclResult = DeclPtrTy(); @@ -1148,6 +1153,13 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, IdentifierInfo *Id = Tok.getIdentifierInfo(); SourceLocation IdLoc = ConsumeToken(); + if (!getLang().CPlusPlus) { + // If we're not in C++, only identifiers matter. Record the + // identifier and return. + Result.setIdentifier(Id, IdLoc); + return false; + } + if (AllowConstructorName && Actions.isCurrentClassName(*Id, CurScope, &SS)) { // We have parsed a constructor name. @@ -1170,12 +1182,41 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, // unqualified-id: // template-id (already parsed and annotated) if (Tok.is(tok::annot_template_id)) { - // FIXME: Could this be a constructor name??? - + TemplateIdAnnotation *TemplateId + = static_cast<TemplateIdAnnotation*>(Tok.getAnnotationValue()); + + // If the template-name names the current class, then this is a constructor + if (AllowConstructorName && TemplateId->Name && + Actions.isCurrentClassName(*TemplateId->Name, CurScope, &SS)) { + if (SS.isSet()) { + // C++ [class.qual]p2 specifies that a qualified template-name + // is taken as the constructor name where a constructor can be + // declared. Thus, the template arguments are extraneous, so + // complain about them and remove them entirely. + Diag(TemplateId->TemplateNameLoc, + diag::err_out_of_line_constructor_template_id) + << TemplateId->Name + << CodeModificationHint::CreateRemoval( + SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)); + Result.setConstructorName(Actions.getTypeName(*TemplateId->Name, + TemplateId->TemplateNameLoc, + CurScope, + &SS, false), + TemplateId->TemplateNameLoc, + TemplateId->RAngleLoc); + TemplateId->Destroy(); + ConsumeToken(); + return false; + } + + Result.setConstructorTemplateId(TemplateId); + ConsumeToken(); + return false; + } + // We have already parsed a template-id; consume the annotation token as // our unqualified-id. - Result.setTemplateId( - static_cast<TemplateIdAnnotation*>(Tok.getAnnotationValue())); + Result.setTemplateId(TemplateId); ConsumeToken(); return false; } @@ -1202,7 +1243,8 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, return false; } - if ((AllowDestructorName || SS.isSet()) && Tok.is(tok::tilde)) { + if (getLang().CPlusPlus && + (AllowDestructorName || SS.isSet()) && Tok.is(tok::tilde)) { // C++ [expr.unary.op]p10: // There is an ambiguity in the unary-expression ~X(), where X is a // class-name. The ambiguity is resolved in favor of treating ~ as a diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 9904a2ca85dc..5e2363535320 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -309,7 +309,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl, llvm::SmallVector<DeclGroupPtrTy, 8> allTUVariables; tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword; - SourceLocation AtEndLoc; + SourceRange AtEnd; while (1) { // If this is a method prototype, parse it. @@ -334,6 +334,14 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl, if (Tok.is(tok::eof)) break; + // Code completion within an Objective-C interface. + if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteOrdinaryName(CurScope, + ObjCImpDecl? Action::CCC_ObjCImplementation + : Action::CCC_ObjCInterface); + ConsumeToken(); + } + // If we don't have an @ directive, parse it as a function definition. if (Tok.isNot(tok::at)) { // The code below does not consume '}'s because it is afraid of eating the @@ -359,7 +367,8 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl, tok::ObjCKeywordKind DirectiveKind = Tok.getObjCKeywordID(); if (DirectiveKind == tok::objc_end) { // @end -> terminate list - AtEndLoc = AtLoc; + AtEnd.setBegin(AtLoc); + AtEnd.setEnd(Tok.getLocation()); break; } @@ -422,7 +431,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl, // Insert collected methods declarations into the @interface object. // This passes in an invalid SourceLocation for AtEndLoc when EOF is hit. - Actions.ActOnAtEnd(AtEndLoc, interfaceDecl, + Actions.ActOnAtEnd(AtEnd, interfaceDecl, allMethods.data(), allMethods.size(), allProperties.data(), allProperties.size(), allTUVariables.data(), allTUVariables.size()); @@ -964,6 +973,12 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl, // Set the default visibility to private. if (Tok.is(tok::at)) { // parse objc-visibility-spec ConsumeToken(); // eat the @ sign + + if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteObjCAtVisibility(CurScope); + ConsumeToken(); + } + switch (Tok.getObjCKeywordID()) { case tok::objc_private: case tok::objc_public: @@ -978,6 +993,12 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl, } } + if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteOrdinaryName(CurScope, + Action::CCC_ObjCInstanceVariableList); + ConsumeToken(); + } + struct ObjCIvarCallback : FieldCallback { Parser &P; DeclPtrTy IDecl; @@ -1197,18 +1218,20 @@ Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration( return DeclPtrTy(); } -Parser::DeclPtrTy Parser::ParseObjCAtEndDeclaration(SourceLocation atLoc) { +Parser::DeclPtrTy Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) { assert(Tok.isObjCAtKeyword(tok::objc_end) && "ParseObjCAtEndDeclaration(): Expected @end"); DeclPtrTy Result = ObjCImpDecl; ConsumeToken(); // the "end" identifier if (ObjCImpDecl) { - Actions.ActOnAtEnd(atLoc, ObjCImpDecl); + Actions.ActOnAtEnd(atEnd, ObjCImpDecl); ObjCImpDecl = DeclPtrTy(); PendingObjCImpDecl.pop_back(); } - else - Diag(atLoc, diag::warn_expected_implementation); // missing @implementation + else { + // missing @implementation + Diag(atEnd.getBegin(), diag::warn_expected_implementation); + } return Result; } @@ -1216,7 +1239,7 @@ Parser::DeclGroupPtrTy Parser::RetrievePendingObjCImpDecl() { if (PendingObjCImpDecl.empty()) return Actions.ConvertDeclToDeclGroup(DeclPtrTy()); DeclPtrTy ImpDecl = PendingObjCImpDecl.pop_back_val(); - Actions.ActOnAtEnd(SourceLocation(), ImpDecl); + Actions.ActOnAtEnd(SourceRange(), ImpDecl); return Actions.ConvertDeclToDeclGroup(ImpDecl); } diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 9085b8713dfd..21e960aa8173 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -95,7 +95,7 @@ Parser::ParseStatementOrDeclaration(bool OnlyStatement) { } case tok::code_completion: - Actions.CodeCompleteOrdinaryName(CurScope); + Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Statement); ConsumeToken(); return ParseStatementOrDeclaration(OnlyStatement); @@ -955,7 +955,9 @@ Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) { DeclPtrTy SecondVar; if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteOrdinaryName(CurScope); + Actions.CodeCompleteOrdinaryName(CurScope, + C99orCXXorObjC? Action::CCC_ForInit + : Action::CCC_Expression); ConsumeToken(); } @@ -1182,7 +1184,7 @@ Parser::OwningStmtResult Parser::FuzzyParseMicrosoftAsmStatement() { return Actions.ActOnAsmStmt(Tok.getLocation(), true, true, 0, 0, Names.data(), move_arg(Constraints), move_arg(Exprs), move(AsmString), move_arg(Clobbers), - Tok.getLocation()); + Tok.getLocation(), true); } /// ParseAsmStatement - Parse a GNU extended asm statement. diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index 8b8af99ec6d7..797c1dfe3e6a 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -196,7 +196,8 @@ Parser::ParseSingleDeclarationAfterTemplate( if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) DS.AddAttributes(ParseCXX0XAttributes().AttrList); - ParseDeclarationSpecifiers(DS, TemplateInfo, AS); + ParseDeclarationSpecifiers(DS, TemplateInfo, AS, + getDeclSpecContextFromDeclaratorContext(Context)); if (Tok.is(tok::semi)) { DeclEnd = ConsumeToken(); diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 52c0153bfad8..0aecac975741 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -455,7 +455,9 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr) SingleDecl = ParseObjCMethodDefinition(); break; case tok::code_completion: - Actions.CodeCompleteOrdinaryName(CurScope); + Actions.CodeCompleteOrdinaryName(CurScope, + ObjCImpDecl? Action::CCC_ObjCImplementation + : Action::CCC_Namespace); ConsumeToken(); return ParseExternalDeclaration(Attr); case tok::kw_using: @@ -541,7 +543,7 @@ Parser::ParseDeclarationOrFunctionDefinition(ParsingDeclSpec &DS, if (Attr) DS.AddAttributes(Attr); - ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS); + ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS, DSC_top_level); // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };" // declaration-specifiers init-declarator-list[opt] ';' |
