diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Parse/ParseObjc.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/Parse/ParseObjc.cpp | 319 |
1 files changed, 196 insertions, 123 deletions
diff --git a/contrib/llvm-project/clang/lib/Parse/ParseObjc.cpp b/contrib/llvm-project/clang/lib/Parse/ParseObjc.cpp index 88942ed173d0..849fd1ac95a4 100644 --- a/contrib/llvm-project/clang/lib/Parse/ParseObjc.cpp +++ b/contrib/llvm-project/clang/lib/Parse/ParseObjc.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ASTContext.h" +#include "clang/AST/ODRDiagsEmitter.h" #include "clang/AST/PrettyDeclStackTrace.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/TargetInfo.h" @@ -46,26 +47,41 @@ void Parser::MaybeSkipAttributes(tok::ObjCKeywordKind Kind) { /// [OBJC] objc-method-definition /// [OBJC] '@' 'end' Parser::DeclGroupPtrTy -Parser::ParseObjCAtDirectives(ParsedAttributesWithRange &Attrs) { +Parser::ParseObjCAtDirectives(ParsedAttributes &DeclAttrs, + ParsedAttributes &DeclSpecAttrs) { + DeclAttrs.takeAllFrom(DeclSpecAttrs); + SourceLocation AtLoc = ConsumeToken(); // the "@" if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCAtDirective(getCurScope()); cutOffParsing(); + Actions.CodeCompleteObjCAtDirective(getCurScope()); return nullptr; } + switch (Tok.getObjCKeywordID()) { + case tok::objc_interface: + case tok::objc_protocol: + case tok::objc_implementation: + break; + default: + for (const auto &Attr : DeclAttrs) { + if (Attr.isGNUAttribute()) + Diag(Tok.getLocation(), diag::err_objc_unexpected_attr); + } + } + Decl *SingleDecl = nullptr; switch (Tok.getObjCKeywordID()) { case tok::objc_class: return ParseObjCAtClassDeclaration(AtLoc); case tok::objc_interface: - SingleDecl = ParseObjCAtInterfaceDeclaration(AtLoc, Attrs); + SingleDecl = ParseObjCAtInterfaceDeclaration(AtLoc, DeclAttrs); break; case tok::objc_protocol: - return ParseObjCAtProtocolDeclaration(AtLoc, Attrs); + return ParseObjCAtProtocolDeclaration(AtLoc, DeclAttrs); case tok::objc_implementation: - return ParseObjCAtImplementationDeclaration(AtLoc, Attrs); + return ParseObjCAtImplementationDeclaration(AtLoc, DeclAttrs); case tok::objc_end: return ParseObjCAtEndDeclaration(AtLoc); case tok::objc_compatibility_alias: @@ -79,7 +95,8 @@ Parser::ParseObjCAtDirectives(ParsedAttributesWithRange &Attrs) { break; case tok::objc_import: if (getLangOpts().Modules || getLangOpts().DebuggerSupport) { - SingleDecl = ParseModuleImport(AtLoc); + Sema::ModuleImportState IS = Sema::ModuleImportState::NotACXX20Module; + SingleDecl = ParseModuleImport(AtLoc, IS); break; } Diag(AtLoc, diag::err_atimport); @@ -134,8 +151,13 @@ Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) { SmallVector<SourceLocation, 8> ClassLocs; SmallVector<ObjCTypeParamList *, 8> ClassTypeParams; - while (1) { + while (true) { MaybeSkipAttributes(tok::objc_class); + if (Tok.is(tok::code_completion)) { + cutOffParsing(); + Actions.CodeCompleteObjCClassForwardDecl(getCurScope()); + return Actions.ConvertDeclToDeclGroup(nullptr); + } if (expectIdentifier()) { SkipUntil(tok::semi); return Actions.ConvertDeclToDeclGroup(nullptr); @@ -219,8 +241,8 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, // Code completion after '@interface'. if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCInterfaceDecl(getCurScope()); cutOffParsing(); + Actions.CodeCompleteObjCInterfaceDecl(getCurScope()); return nullptr; } @@ -253,8 +275,8 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, SourceLocation categoryLoc; IdentifierInfo *categoryId = nullptr; if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCInterfaceCategory(getCurScope(), nameId, nameLoc); cutOffParsing(); + Actions.CodeCompleteObjCInterfaceCategory(getCurScope(), nameId, nameLoc); return nullptr; } @@ -283,7 +305,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, /*consumeLastToken=*/true)) return nullptr; - Decl *CategoryType = Actions.ActOnStartCategoryInterface( + ObjCCategoryDecl *CategoryType = Actions.ActOnStartCategoryInterface( AtLoc, nameId, nameLoc, typeParameterList, categoryId, categoryLoc, ProtocolRefs.data(), ProtocolRefs.size(), ProtocolLocs.data(), EndProtoLoc, attrs); @@ -308,8 +330,8 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, // Code completion of superclass names. if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCSuperclass(getCurScope(), nameId, nameLoc); cutOffParsing(); + Actions.CodeCompleteObjCSuperclass(getCurScope(), nameId, nameLoc); return nullptr; } @@ -353,17 +375,30 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, Actions.ActOnTypedefedProtocols(protocols, protocolLocs, superClassId, superClassLoc); - Decl *ClsType = Actions.ActOnStartClassInterface( + Sema::SkipBodyInfo SkipBody; + ObjCInterfaceDecl *ClsType = Actions.ActOnStartClassInterface( getCurScope(), AtLoc, nameId, nameLoc, typeParameterList, superClassId, superClassLoc, typeArgs, SourceRange(typeArgsLAngleLoc, typeArgsRAngleLoc), protocols.data(), - protocols.size(), protocolLocs.data(), EndProtoLoc, attrs); + protocols.size(), protocolLocs.data(), EndProtoLoc, attrs, &SkipBody); if (Tok.is(tok::l_brace)) ParseObjCClassInstanceVariables(ClsType, tok::objc_protected, AtLoc); ParseObjCInterfaceDeclList(tok::objc_interface, ClsType); + if (SkipBody.CheckSameAsPrevious) { + auto *PreviousDef = cast<ObjCInterfaceDecl>(SkipBody.Previous); + if (Actions.ActOnDuplicateODRHashDefinition(ClsType, PreviousDef)) { + ClsType->mergeDuplicateDefinitionWithCommon(PreviousDef->getDefinition()); + } else { + ODRDiagsEmitter DiagsEmitter(Diags, Actions.getASTContext(), + getPreprocessor().getLangOpts()); + DiagsEmitter.diagnoseMismatch(PreviousDef, ClsType); + ClsType->setInvalidDecl(); + } + } + return ClsType; } @@ -378,7 +413,7 @@ static void addContextSensitiveTypeNullability(Parser &P, auto getNullabilityAttr = [&](AttributePool &Pool) -> ParsedAttr * { return Pool.create(P.getNullabilityKeyword(nullability), SourceRange(nullabilityLoc), nullptr, SourceLocation(), - nullptr, 0, ParsedAttr::AS_ContextSensitiveKeyword); + nullptr, 0, ParsedAttr::Form::ContextSensitiveKeyword()); }; if (D.getNumTypeObjects() > 0) { @@ -472,8 +507,8 @@ ObjCTypeParamList *Parser::parseObjCTypeParamListOrProtocolRefs( if (Tok.is(tok::code_completion)) { // FIXME: If these aren't protocol references, we'll need different // completions. - Actions.CodeCompleteObjCProtocolReferences(protocolIdents); cutOffParsing(); + Actions.CodeCompleteObjCProtocolReferences(protocolIdents); // FIXME: Better recovery here?. return nullptr; @@ -578,6 +613,19 @@ ObjCTypeParamList *Parser::parseObjCTypeParamList() { /*mayBeProtocolList=*/false); } +static bool isTopLevelObjCKeyword(tok::ObjCKeywordKind DirectiveKind) { + switch (DirectiveKind) { + case tok::objc_class: + case tok::objc_compatibility_alias: + case tok::objc_interface: + case tok::objc_implementation: + case tok::objc_protocol: + return true; + default: + return false; + } +} + /// objc-interface-decl-list: /// empty /// objc-interface-decl-list objc-property-decl [OBJC2] @@ -598,7 +646,7 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, SourceRange AtEnd; - while (1) { + while (true) { // If this is a method prototype, parse it. if (Tok.isOneOf(tok::minus, tok::plus)) { if (Decl *methodPrototype = @@ -635,10 +683,11 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, // Code completion within an Objective-C interface. if (Tok.is(tok::code_completion)) { + cutOffParsing(); Actions.CodeCompleteOrdinaryName(getCurScope(), CurParsedObjCImpl? Sema::PCC_ObjCImplementation : Sema::PCC_ObjCInterface); - return cutOffParsing(); + return; } // If we don't have an @ directive, parse it as a function definition. @@ -649,42 +698,54 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, if (Tok.is(tok::r_brace)) break; - ParsedAttributesWithRange attrs(AttrFactory); + ParsedAttributes EmptyDeclAttrs(AttrFactory); + ParsedAttributes EmptyDeclSpecAttrs(AttrFactory); // Since we call ParseDeclarationOrFunctionDefinition() instead of // ParseExternalDeclaration() below (so that this doesn't parse nested // @interfaces), this needs to duplicate some code from the latter. if (Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert)) { SourceLocation DeclEnd; - allTUVariables.push_back( - ParseDeclaration(DeclaratorContext::File, DeclEnd, attrs)); + ParsedAttributes EmptyDeclSpecAttrs(AttrFactory); + allTUVariables.push_back(ParseDeclaration(DeclaratorContext::File, + DeclEnd, EmptyDeclAttrs, + EmptyDeclSpecAttrs)); continue; } - allTUVariables.push_back(ParseDeclarationOrFunctionDefinition(attrs)); + allTUVariables.push_back(ParseDeclarationOrFunctionDefinition( + EmptyDeclAttrs, EmptyDeclSpecAttrs)); continue; } - // Otherwise, we have an @ directive, eat the @. - SourceLocation AtLoc = ConsumeToken(); // the "@" - if (Tok.is(tok::code_completion)) { + // Otherwise, we have an @ directive, peak at the next token + SourceLocation AtLoc = Tok.getLocation(); + const auto &NextTok = NextToken(); + if (NextTok.is(tok::code_completion)) { + cutOffParsing(); Actions.CodeCompleteObjCAtDirective(getCurScope()); - return cutOffParsing(); + return; } - tok::ObjCKeywordKind DirectiveKind = Tok.getObjCKeywordID(); - + tok::ObjCKeywordKind DirectiveKind = NextTok.getObjCKeywordID(); if (DirectiveKind == tok::objc_end) { // @end -> terminate list + ConsumeToken(); // the "@" AtEnd.setBegin(AtLoc); AtEnd.setEnd(Tok.getLocation()); break; } else if (DirectiveKind == tok::objc_not_keyword) { - Diag(Tok, diag::err_objc_unknown_at); + Diag(NextTok, diag::err_objc_unknown_at); SkipUntil(tok::semi); continue; } - // Eat the identifier. + // If we see something like '@interface' that's only allowed at the top + // level, bail out as if we saw an '@end'. We'll diagnose this below. + if (isTopLevelObjCKeyword(DirectiveKind)) + break; + + // Otherwise parse it as part of the current declaration. Eat "@identifier". + ConsumeToken(); ConsumeToken(); switch (DirectiveKind) { @@ -698,15 +759,6 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, SkipUntil(tok::r_brace, tok::at, StopAtSemi); break; - case tok::objc_implementation: - case tok::objc_interface: - Diag(AtLoc, diag::err_objc_missing_end) - << FixItHint::CreateInsertion(AtLoc, "@end\n"); - Diag(CDecl->getBeginLoc(), diag::note_objc_container_start) - << (int)Actions.getObjCContainerKind(); - ConsumeToken(); - break; - case tok::objc_required: case tok::objc_optional: // This is only valid on protocols. @@ -775,12 +827,10 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, } } - // We break out of the big loop in two cases: when we see @end or when we see - // EOF. In the former case, eat the @end. In the later case, emit an error. - if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCAtDirective(getCurScope()); - return cutOffParsing(); - } else if (Tok.isObjCAtKeyword(tok::objc_end)) { + // We break out of the big loop in 3 cases: when we see @end or when we see + // top-level ObjC keyword or EOF. In the former case, eat the @end. In the + // later cases, emit an error. + if (Tok.isObjCAtKeyword(tok::objc_end)) { ConsumeToken(); // the "end" identifier } else { Diag(Tok, diag::err_objc_missing_end) @@ -845,10 +895,11 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) { BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); - while (1) { + while (true) { if (Tok.is(tok::code_completion)) { + cutOffParsing(); Actions.CodeCompleteObjCPropertyFlags(getCurScope(), DS); - return cutOffParsing(); + return; } const IdentifierInfo *II = Tok.getIdentifierInfo(); @@ -893,11 +944,12 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) { } if (Tok.is(tok::code_completion)) { + cutOffParsing(); if (IsSetter) Actions.CodeCompleteObjCPropertySetter(getCurScope()); else Actions.CodeCompleteObjCPropertyGetter(getCurScope()); - return cutOffParsing(); + return; } SourceLocation SelLoc; @@ -1144,11 +1196,12 @@ void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS, assert(Context == DeclaratorContext::ObjCParameter || Context == DeclaratorContext::ObjCResult); - while (1) { + while (true) { if (Tok.is(tok::code_completion)) { + cutOffParsing(); Actions.CodeCompleteObjCPassingType( getCurScope(), DS, Context == DeclaratorContext::ObjCParameter); - return cutOffParsing(); + return; } if (Tok.isNot(tok::identifier)) @@ -1219,6 +1272,10 @@ static void takeDeclAttributes(ParsedAttributesView &attrs, /// declarator and add them to the given list. static void takeDeclAttributes(ParsedAttributes &attrs, Declarator &D) { + // This gets called only from Parser::ParseObjCTypeName(), and that should + // never add declaration attributes to the Declarator. + assert(D.getDeclarationAttributes().empty()); + // First, take ownership of all attributes. attrs.getPool().takeAllFrom(D.getAttributePool()); attrs.getPool().takeAllFrom(D.getDeclSpec().getAttributePool()); @@ -1262,7 +1319,7 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS, if (context == DeclaratorContext::ObjCResult) dsContext = DeclSpecContext::DSC_objc_method_result; ParseSpecifierQualifierList(declSpec, AS_none, dsContext); - Declarator declarator(declSpec, context); + Declarator declarator(declSpec, ParsedAttributesView::none(), context); ParseDeclarator(declarator); // If that's not invalid, extract a type. @@ -1275,7 +1332,7 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS, DS.getNullabilityLoc(), addedToDeclSpec); - TypeResult type = Actions.ActOnTypeName(getCurScope(), declarator); + TypeResult type = Actions.ActOnTypeName(declarator); if (!type.isInvalid()) Ty = type.get(); @@ -1335,9 +1392,9 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent); if (Tok.is(tok::code_completion)) { + cutOffParsing(); Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus, /*ReturnType=*/nullptr); - cutOffParsing(); return nullptr; } @@ -1350,14 +1407,13 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, // If attributes exist before the method, parse them. ParsedAttributes methodAttrs(AttrFactory); - if (getLangOpts().ObjC) - MaybeParseGNUAttributes(methodAttrs); - MaybeParseCXX11Attributes(methodAttrs); + MaybeParseAttributes(PAKM_CXX11 | (getLangOpts().ObjC ? PAKM_GNU : 0), + methodAttrs); if (Tok.is(tok::code_completion)) { + cutOffParsing(); Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus, ReturnType); - cutOffParsing(); return nullptr; } @@ -1377,9 +1433,8 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, SmallVector<DeclaratorChunk::ParamInfo, 8> CParamInfo; if (Tok.isNot(tok::colon)) { // If attributes exist after the method, parse them. - if (getLangOpts().ObjC) - MaybeParseGNUAttributes(methodAttrs); - MaybeParseCXX11Attributes(methodAttrs); + MaybeParseAttributes(PAKM_CXX11 | (getLangOpts().ObjC ? PAKM_GNU : 0), + methodAttrs); Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent); Decl *Result = Actions.ActOnMethodDeclaration( @@ -1397,7 +1452,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, Scope::FunctionDeclarationScope | Scope::DeclScope); AttributePool allParamAttrs(AttrFactory); - while (1) { + while (true) { ParsedAttributes paramAttrs(AttrFactory); Sema::ObjCArgInfo ArgInfo; @@ -1412,19 +1467,18 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, // If attributes exist before the argument name, parse them. // Regardless, collect all the attributes we've parsed so far. - if (getLangOpts().ObjC) - MaybeParseGNUAttributes(paramAttrs); - MaybeParseCXX11Attributes(paramAttrs); + MaybeParseAttributes(PAKM_CXX11 | (getLangOpts().ObjC ? PAKM_GNU : 0), + paramAttrs); ArgInfo.ArgAttrs = paramAttrs; // Code completion for the next piece of the selector. if (Tok.is(tok::code_completion)) { + cutOffParsing(); KeyIdents.push_back(SelIdent); Actions.CodeCompleteObjCMethodDeclSelector(getCurScope(), mType == tok::minus, /*AtParameterName=*/true, ReturnType, KeyIdents); - cutOffParsing(); return nullptr; } @@ -1444,11 +1498,11 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, // Code completion for the next piece of the selector. if (Tok.is(tok::code_completion)) { + cutOffParsing(); Actions.CodeCompleteObjCMethodDeclSelector(getCurScope(), mType == tok::minus, /*AtParameterName=*/false, ReturnType, KeyIdents); - cutOffParsing(); return nullptr; } @@ -1484,7 +1538,8 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, DeclSpec DS(AttrFactory); ParseDeclarationSpecifiers(DS); // Parse the declarator. - Declarator ParmDecl(DS, DeclaratorContext::Prototype); + Declarator ParmDecl(DS, ParsedAttributesView::none(), + DeclaratorContext::Prototype); ParseDeclarator(ParmDecl); IdentifierInfo *ParmII = ParmDecl.getIdentifier(); Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDecl); @@ -1496,9 +1551,8 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, // FIXME: Add support for optional parameter list... // If attributes exist after the method, parse them. - if (getLangOpts().ObjC) - MaybeParseGNUAttributes(methodAttrs); - MaybeParseCXX11Attributes(methodAttrs); + MaybeParseAttributes(PAKM_CXX11 | (getLangOpts().ObjC ? PAKM_GNU : 0), + methodAttrs); if (KeyIdents.size() == 0) return nullptr; @@ -1529,10 +1583,10 @@ ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols, SmallVector<IdentifierLocPair, 8> ProtocolIdents; - while (1) { + while (true) { if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCProtocolReferences(ProtocolIdents); cutOffParsing(); + Actions.CodeCompleteObjCProtocolReferences(ProtocolIdents); return true; } @@ -1630,12 +1684,12 @@ void Parser::parseObjCTypeArgsOrProtocolQualifiers( } QualType BaseT = Actions.GetTypeFromParser(baseType); + cutOffParsing(); if (!BaseT.isNull() && BaseT->acceptsObjCTypeParams()) { Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Type); } else { Actions.CodeCompleteObjCProtocolReferences(identifierLocPairs); } - cutOffParsing(); return; } @@ -1691,8 +1745,9 @@ void Parser::parseObjCTypeArgsOrProtocolQualifiers( typeArg, Actions.getASTContext().getPrintingPolicy()); // Form a declarator to turn this into a type. - Declarator D(DS, DeclaratorContext::TypeName); - TypeResult fullTypeArg = Actions.ActOnTypeName(getCurScope(), D); + Declarator D(DS, ParsedAttributesView::none(), + DeclaratorContext::TypeName); + TypeResult fullTypeArg = Actions.ActOnTypeName(D); if (fullTypeArg.isUsable()) { typeArgs.push_back(fullTypeArg.get()); if (!foundValidTypeId) { @@ -1862,16 +1917,16 @@ TypeResult Parser::parseObjCTypeArgsAndProtocolQualifiers( protocolRAngleLoc); } -void Parser::HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocation atLoc, - BalancedDelimiterTracker &T, - SmallVectorImpl<Decl *> &AllIvarDecls, - bool RBraceMissing) { +void Parser::HelperActionsForIvarDeclarations( + ObjCContainerDecl *interfaceDecl, SourceLocation atLoc, + BalancedDelimiterTracker &T, SmallVectorImpl<Decl *> &AllIvarDecls, + bool RBraceMissing) { if (!RBraceMissing) T.consumeClose(); - Actions.ActOnObjCContainerStartDefinition(interfaceDecl); + assert(getObjCDeclContext() == interfaceDecl && + "Ivars should have interfaceDecl as their decl context"); Actions.ActOnLastBitfield(T.getCloseLocation(), AllIvarDecls); - Actions.ActOnObjCContainerFinishDefinition(); // Call ActOnFields() even if we don't have any decls. This is useful // for code rewriting tools that need to be aware of the empty list. Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl, AllIvarDecls, @@ -1900,14 +1955,13 @@ void Parser::HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocatio /// objc-instance-variable-decl: /// struct-declaration /// -void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, +void Parser::ParseObjCClassInstanceVariables(ObjCContainerDecl *interfaceDecl, tok::ObjCKeywordKind visibility, SourceLocation atLoc) { assert(Tok.is(tok::l_brace) && "expected {"); SmallVector<Decl *, 32> AllIvarDecls; - ParseScope ClassScope(this, Scope::DeclScope|Scope::ClassScope); - ObjCDeclContextSwitch ObjCDC(*this); + ParseScope ClassScope(this, Scope::DeclScope | Scope::ClassScope); BalancedDelimiterTracker T(*this, tok::l_brace); T.consumeOpen(); @@ -1924,8 +1978,9 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, // Set the default visibility to private. if (TryConsumeToken(tok::at)) { // parse objc-visibility-spec if (Tok.is(tok::code_completion)) { + cutOffParsing(); Actions.CodeCompleteObjCAtVisibility(getCurScope()); - return cutOffParsing(); + return; } switch (Tok.getObjCKeywordID()) { @@ -1954,9 +2009,10 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, } if (Tok.is(tok::code_completion)) { + cutOffParsing(); Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_ObjCInstanceVariableList); - return cutOffParsing(); + return; } // This needs to duplicate a small amount of code from @@ -1969,13 +2025,13 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, } auto ObjCIvarCallback = [&](ParsingFieldDeclarator &FD) { - Actions.ActOnObjCContainerStartDefinition(interfaceDecl); + assert(getObjCDeclContext() == interfaceDecl && + "Ivar should have interfaceDecl as its decl context"); // Install the declarator into the interface decl. FD.D.setObjCIvar(true); Decl *Field = Actions.ActOnIvar( getCurScope(), FD.D.getDeclSpec().getSourceRange().getBegin(), FD.D, FD.BitfieldSize, visibility); - Actions.ActOnObjCContainerFinishDefinition(); if (Field) AllIvarDecls.push_back(Field); FD.complete(Field); @@ -2021,8 +2077,8 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, ConsumeToken(); // the "protocol" identifier if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCProtocolDecl(getCurScope()); cutOffParsing(); + Actions.CodeCompleteObjCProtocolDecl(getCurScope()); return nullptr; } @@ -2046,7 +2102,7 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, ProtocolRefs.push_back(std::make_pair(protocolName, nameLoc)); // Parse the list of forward declarations. - while (1) { + while (true) { ConsumeToken(); // the ',' if (expectIdentifier()) { SkipUntil(tok::semi); @@ -2077,11 +2133,23 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, /*consumeLastToken=*/true)) return nullptr; - Decl *ProtoType = Actions.ActOnStartProtocolInterface( + Sema::SkipBodyInfo SkipBody; + ObjCProtocolDecl *ProtoType = Actions.ActOnStartProtocolInterface( AtLoc, protocolName, nameLoc, ProtocolRefs.data(), ProtocolRefs.size(), - ProtocolLocs.data(), EndProtoLoc, attrs); + ProtocolLocs.data(), EndProtoLoc, attrs, &SkipBody); ParseObjCInterfaceDeclList(tok::objc_protocol, ProtoType); + if (SkipBody.CheckSameAsPrevious) { + auto *PreviousDef = cast<ObjCProtocolDecl>(SkipBody.Previous); + if (Actions.ActOnDuplicateODRHashDefinition(ProtoType, PreviousDef)) { + ProtoType->mergeDuplicateDefinitionWithCommon( + PreviousDef->getDefinition()); + } else { + ODRDiagsEmitter DiagsEmitter(Diags, Actions.getASTContext(), + getPreprocessor().getLangOpts()); + DiagsEmitter.diagnoseMismatch(PreviousDef, ProtoType); + } + } return Actions.ConvertDeclToDeclGroup(ProtoType); } @@ -2105,8 +2173,8 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc, // Code completion after '@implementation'. if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCImplementationDecl(getCurScope()); cutOffParsing(); + Actions.CodeCompleteObjCImplementationDecl(getCurScope()); return nullptr; } @@ -2117,7 +2185,7 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc, // We have a class or category name - consume it. IdentifierInfo *nameId = Tok.getIdentifierInfo(); SourceLocation nameLoc = ConsumeToken(); // consume class or category name - Decl *ObjCImpDecl = nullptr; + ObjCImplDecl *ObjCImpDecl = nullptr; // Neither a type parameter list nor a list of protocol references is // permitted here. Parse and diagnose them. @@ -2143,8 +2211,8 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc, IdentifierInfo *categoryId = nullptr; if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCImplementationCategory(getCurScope(), nameId, nameLoc); cutOffParsing(); + Actions.CodeCompleteObjCImplementationCategory(getCurScope(), nameId, nameLoc); return nullptr; } @@ -2212,9 +2280,11 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc, { ObjCImplParsingDataRAII ObjCImplParsing(*this, ObjCImpDecl); while (!ObjCImplParsing.isFinished() && !isEofOrEom()) { - ParsedAttributesWithRange attrs(AttrFactory); - MaybeParseCXX11Attributes(attrs); - if (DeclGroupPtrTy DGP = ParseExternalDeclaration(attrs)) { + ParsedAttributes DeclAttrs(AttrFactory); + MaybeParseCXX11Attributes(DeclAttrs); + ParsedAttributes EmptyDeclSpecAttrs(AttrFactory); + if (DeclGroupPtrTy DGP = + ParseExternalDeclaration(DeclAttrs, EmptyDeclSpecAttrs)) { DeclGroupRef DG = DGP.get(); DeclsInGroup.append(DG.begin(), DG.end()); } @@ -2313,8 +2383,8 @@ Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { while (true) { if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCPropertyDefinition(getCurScope()); cutOffParsing(); + Actions.CodeCompleteObjCPropertyDefinition(getCurScope()); return nullptr; } @@ -2331,8 +2401,8 @@ Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { if (TryConsumeToken(tok::equal)) { // property '=' ivar-name if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCPropertySynthesizeIvar(getCurScope(), propertyId); cutOffParsing(); + Actions.CodeCompleteObjCPropertySynthesizeIvar(getCurScope(), propertyId); return nullptr; } @@ -2391,8 +2461,8 @@ Decl *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) { while (true) { if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCPropertyDefinition(getCurScope()); cutOffParsing(); + Actions.CodeCompleteObjCPropertyDefinition(getCurScope()); return nullptr; } @@ -2535,7 +2605,8 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { if (Tok.isNot(tok::ellipsis)) { DeclSpec DS(AttrFactory); ParseDeclarationSpecifiers(DS); - Declarator ParmDecl(DS, DeclaratorContext::ObjCCatch); + Declarator ParmDecl(DS, ParsedAttributesView::none(), + DeclaratorContext::ObjCCatch); ParseDeclarator(ParmDecl); // Inform the actions module about the declarator, so it @@ -2728,8 +2799,8 @@ Decl *Parser::ParseObjCMethodDefinition() { StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc, ParsedStmtContext StmtCtx) { if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCAtStatement(getCurScope()); cutOffParsing(); + Actions.CodeCompleteObjCAtStatement(getCurScope()); return StmtError(); } @@ -2769,8 +2840,8 @@ StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc, ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { switch (Tok.getKind()) { case tok::code_completion: - Actions.CodeCompleteObjCAtExpression(getCurScope()); cutOffParsing(); + Actions.CodeCompleteObjCAtExpression(getCurScope()); return ExprError(); case tok::minus: @@ -2951,8 +3022,9 @@ bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) { // We have a class message. Turn the simple-type-specifier or // typename-specifier we parsed into a type and parse the // remainder of the class message. - Declarator DeclaratorInfo(DS, DeclaratorContext::TypeName); - TypeResult Type = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); + Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), + DeclaratorContext::TypeName); + TypeResult Type = Actions.ActOnTypeName(DeclaratorInfo); if (Type.isInvalid()) return true; @@ -3016,8 +3088,8 @@ ExprResult Parser::ParseObjCMessageExpression() { SourceLocation LBracLoc = ConsumeBracket(); // consume '[' if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCMessageReceiver(getCurScope()); cutOffParsing(); + Actions.CodeCompleteObjCMessageReceiver(getCurScope()); return ExprError(); } @@ -3153,16 +3225,16 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, InMessageExpressionRAIIObject InMessage(*this, true); if (Tok.is(tok::code_completion)) { + cutOffParsing(); if (SuperLoc.isValid()) - Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc, None, - false); + Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc, + std::nullopt, false); else if (ReceiverType) - Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType, None, - false); + Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType, + std::nullopt, false); else Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr, - None, false); - cutOffParsing(); + std::nullopt, false); return ExprError(); } @@ -3175,7 +3247,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, ExprVector KeyExprs; if (Tok.is(tok::colon)) { - while (1) { + while (true) { // Each iteration parses a single keyword argument. KeyIdents.push_back(selIdent); KeyLocs.push_back(Loc); @@ -3191,6 +3263,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, /// Parse the expression after ':' if (Tok.is(tok::code_completion)) { + cutOffParsing(); if (SuperLoc.isValid()) Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc, KeyIdents, @@ -3204,7 +3277,6 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, KeyIdents, /*AtArgumentExpression=*/true); - cutOffParsing(); return ExprError(); } @@ -3229,6 +3301,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, // Code completion after each argument. if (Tok.is(tok::code_completion)) { + cutOffParsing(); if (SuperLoc.isValid()) Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc, KeyIdents, @@ -3241,7 +3314,6 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr, KeyIdents, /*AtArgumentExpression=*/false); - cutOffParsing(); return ExprError(); } @@ -3494,9 +3566,8 @@ ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) { // We have a valid expression. Collect it in a vector so we can // build the argument list. - ObjCDictionaryElement Element = { - KeyExpr.get(), ValueExpr.get(), EllipsisLoc, None - }; + ObjCDictionaryElement Element = {KeyExpr.get(), ValueExpr.get(), + EllipsisLoc, std::nullopt}; Elements.push_back(Element); if (!TryConsumeToken(tok::comma) && Tok.isNot(tok::r_brace)) @@ -3581,8 +3652,8 @@ ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) { ConsumeParen(); if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents); cutOffParsing(); + Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents); return ExprError(); } @@ -3595,7 +3666,7 @@ ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) { unsigned nColons = 0; if (Tok.isNot(tok::r_paren)) { - while (1) { + while (true) { if (TryConsumeToken(tok::coloncolon)) { // Handle :: in C++. ++nColons; KeyIdents.push_back(nullptr); @@ -3607,8 +3678,8 @@ ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) { break; if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents); cutOffParsing(); + Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents); return ExprError(); } @@ -3693,6 +3764,8 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) { while (Tok.getLocation() != OrigLoc && Tok.isNot(tok::eof)) ConsumeAnyToken(); } - // Clean up the remaining EOF token. - ConsumeAnyToken(); + // Clean up the remaining EOF token, only if it's inserted by us. Otherwise + // this might be code-completion token, which must be propagated to callers. + if (Tok.is(tok::eof) && Tok.getEofData() == MCDecl) + ConsumeAnyToken(); } |