Skip to content

Commit

Permalink
[ObjC] Insert method parameters in scope as they are parsed (llvm#113745
Browse files Browse the repository at this point in the history
)

Before this change, ParseObjc would call the closing
`MaybeParseAttributes` before it had created Objective-C `ParmVarDecl`
objects (and associated name lookup entries), meaning that you could not
reference Objective-C method parameters in
`__attribute__((diagnose_if))`. This change moves the creation of the
`ParmVarDecl` objects ahead of calling `Sema::ActOnMethodDeclaration` so
that `MaybeParseAttributes` can find them. This is already how it works
for C parameters hanging off of the selector.

This change alone is insufficient to enable `diagnose_if` for
Objective-C methods and effectively is NFC. There will be a follow-up PR
for diagnose_if. This change is still useful for any other work that may
need attributes to reference Objective-C parameters.

rdar://138596211
  • Loading branch information
apple-fcloutier authored Oct 31, 2024
1 parent 75aaa31 commit 9778808
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 59 deletions.
6 changes: 5 additions & 1 deletion clang/include/clang/Sema/SemaObjC.h
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,10 @@ class SemaObjC : public SemaBase {
ParsedAttributesView ArgAttrs;
};

ParmVarDecl *ActOnMethodParmDeclaration(Scope *S, ObjCArgInfo &ArgInfo,
int ParamIndex,
bool MethodDefinition);

Decl *ActOnMethodDeclaration(
Scope *S,
SourceLocation BeginLoc, // location of the + or -.
Expand All @@ -359,7 +363,7 @@ class SemaObjC : public SemaBase {
ArrayRef<SourceLocation> SelectorLocs, Selector Sel,
// optional arguments. The number of types/arguments is obtained
// from the Sel.getNumArgs().
ObjCArgInfo *ArgInfo, DeclaratorChunk::ParamInfo *CParamInfo,
ParmVarDecl **ArgInfo, DeclaratorChunk::ParamInfo *CParamInfo,
unsigned CNumArgs, // c-style args
const ParsedAttributesView &AttrList, tok::ObjCKeywordKind MethodImplKind,
bool isVariadic, bool MethodDefinition);
Expand Down
10 changes: 6 additions & 4 deletions clang/lib/Parse/ParseObjc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1454,7 +1454,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,

SmallVector<const IdentifierInfo *, 12> KeyIdents;
SmallVector<SourceLocation, 12> KeyLocs;
SmallVector<SemaObjC::ObjCArgInfo, 12> ArgInfos;
SmallVector<ParmVarDecl *, 12> ObjCParamInfo;
ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope |
Scope::FunctionDeclarationScope | Scope::DeclScope);

Expand Down Expand Up @@ -1495,7 +1495,9 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
ArgInfo.NameLoc = Tok.getLocation();
ConsumeToken(); // Eat the identifier.

ArgInfos.push_back(ArgInfo);
ParmVarDecl *Param = Actions.ObjC().ActOnMethodParmDeclaration(
getCurScope(), ArgInfo, ObjCParamInfo.size(), MethodDefinition);
ObjCParamInfo.push_back(Param);
KeyIdents.push_back(SelIdent);
KeyLocs.push_back(selLoc);

Expand Down Expand Up @@ -1567,8 +1569,8 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
&KeyIdents[0]);
Decl *Result = Actions.ObjC().ActOnMethodDeclaration(
getCurScope(), mLoc, Tok.getLocation(), mType, DSRet, ReturnType, KeyLocs,
Sel, &ArgInfos[0], CParamInfo.data(), CParamInfo.size(), methodAttrs,
MethodImplKind, isVariadic, MethodDefinition);
Sel, ObjCParamInfo.data(), CParamInfo.data(), CParamInfo.size(),
methodAttrs, MethodImplKind, isVariadic, MethodDefinition);

PD.complete(Result);
return Result;
Expand Down
112 changes: 58 additions & 54 deletions clang/lib/Sema/SemaDeclObjC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4720,13 +4720,67 @@ static void checkObjCDirectMethodClashes(Sema &S, ObjCInterfaceDecl *IDecl,
diagClash(IMD);
}

ParmVarDecl *SemaObjC::ActOnMethodParmDeclaration(Scope *S,
ObjCArgInfo &ArgInfo,
int ParamIndex,
bool MethodDefinition) {
ASTContext &Context = getASTContext();
QualType ArgType;
TypeSourceInfo *DI;

if (!ArgInfo.Type) {
ArgType = Context.getObjCIdType();
DI = nullptr;
} else {
ArgType = SemaRef.GetTypeFromParser(ArgInfo.Type, &DI);
}
LookupResult R(SemaRef, ArgInfo.Name, ArgInfo.NameLoc,
Sema::LookupOrdinaryName,
SemaRef.forRedeclarationInCurContext());
SemaRef.LookupName(R, S);
if (R.isSingleResult()) {
NamedDecl *PrevDecl = R.getFoundDecl();
if (S->isDeclScope(PrevDecl)) {
Diag(ArgInfo.NameLoc,
(MethodDefinition ? diag::warn_method_param_redefinition
: diag::warn_method_param_declaration))
<< ArgInfo.Name;
Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
}
}
SourceLocation StartLoc =
DI ? DI->getTypeLoc().getBeginLoc() : ArgInfo.NameLoc;

// Temporarily put parameter variables in the translation unit. This is what
// ActOnParamDeclarator does in the case of C arguments to the Objective-C
// method too.
ParmVarDecl *Param = SemaRef.CheckParameter(
Context.getTranslationUnitDecl(), StartLoc, ArgInfo.NameLoc, ArgInfo.Name,
ArgType, DI, SC_None);
Param->setObjCMethodScopeInfo(ParamIndex);
Param->setObjCDeclQualifier(
CvtQTToAstBitMask(ArgInfo.DeclSpec.getObjCDeclQualifier()));

// Apply the attributes to the parameter.
SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, Param, ArgInfo.ArgAttrs);
SemaRef.AddPragmaAttributes(SemaRef.TUScope, Param);
if (Param->hasAttr<BlocksAttr>()) {
Diag(Param->getLocation(), diag::err_block_on_nonlocal);
Param->setInvalidDecl();
}

S->AddDecl(Param);
SemaRef.IdResolver.AddDecl(Param);
return Param;
}

Decl *SemaObjC::ActOnMethodDeclaration(
Scope *S, SourceLocation MethodLoc, SourceLocation EndLoc,
tok::TokenKind MethodType, ObjCDeclSpec &ReturnQT, ParsedType ReturnType,
ArrayRef<SourceLocation> SelectorLocs, Selector Sel,
// optional arguments. The number of types/arguments is obtained
// from the Sel.getNumArgs().
ObjCArgInfo *ArgInfo, DeclaratorChunk::ParamInfo *CParamInfo,
ParmVarDecl **ArgInfo, DeclaratorChunk::ParamInfo *CParamInfo,
unsigned CNumArgs, // c-style args
const ParsedAttributesView &AttrList, tok::ObjCKeywordKind MethodDeclKind,
bool isVariadic, bool MethodDefinition) {
Expand Down Expand Up @@ -4768,60 +4822,10 @@ Decl *SemaObjC::ActOnMethodDeclaration(
HasRelatedResultType);

SmallVector<ParmVarDecl*, 16> Params;

for (unsigned i = 0, e = Sel.getNumArgs(); i != e; ++i) {
QualType ArgType;
TypeSourceInfo *DI;

if (!ArgInfo[i].Type) {
ArgType = Context.getObjCIdType();
DI = nullptr;
} else {
ArgType = SemaRef.GetTypeFromParser(ArgInfo[i].Type, &DI);
}

LookupResult R(SemaRef, ArgInfo[i].Name, ArgInfo[i].NameLoc,
Sema::LookupOrdinaryName,
SemaRef.forRedeclarationInCurContext());
SemaRef.LookupName(R, S);
if (R.isSingleResult()) {
NamedDecl *PrevDecl = R.getFoundDecl();
if (S->isDeclScope(PrevDecl)) {
Diag(ArgInfo[i].NameLoc,
(MethodDefinition ? diag::warn_method_param_redefinition
: diag::warn_method_param_declaration))
<< ArgInfo[i].Name;
Diag(PrevDecl->getLocation(),
diag::note_previous_declaration);
}
}

SourceLocation StartLoc = DI
? DI->getTypeLoc().getBeginLoc()
: ArgInfo[i].NameLoc;

ParmVarDecl *Param =
SemaRef.CheckParameter(ObjCMethod, StartLoc, ArgInfo[i].NameLoc,
ArgInfo[i].Name, ArgType, DI, SC_None);

Param->setObjCMethodScopeInfo(i);

Param->setObjCDeclQualifier(
CvtQTToAstBitMask(ArgInfo[i].DeclSpec.getObjCDeclQualifier()));

// Apply the attributes to the parameter.
SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, Param,
ArgInfo[i].ArgAttrs);
SemaRef.AddPragmaAttributes(SemaRef.TUScope, Param);
for (unsigned I = 0; I < Sel.getNumArgs(); ++I) {
ParmVarDecl *Param = ArgInfo[I];
Param->setDeclContext(ObjCMethod);
SemaRef.ProcessAPINotes(Param);

if (Param->hasAttr<BlocksAttr>()) {
Diag(Param->getLocation(), diag::err_block_on_nonlocal);
Param->setInvalidDecl();
}
S->AddDecl(Param);
SemaRef.IdResolver.AddDecl(Param);

Params.push_back(Param);
}

Expand Down

0 comments on commit 9778808

Please sign in to comment.