aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Parse/ParseObjc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/Parse/ParseObjc.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/Parse/ParseObjc.cpp319
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();
}