[clang] [ObjC] Insert method parameters in scope as they are parsed (PR #113745)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 30 13:07:25 PDT 2024
https://github.com/apple-fcloutier updated https://github.com/llvm/llvm-project/pull/113745
>From 48013dd32b3fdf6d80f5109c47a2f30a92baf99f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?F=C3=A9lix=20Cloutier?= <fcloutier at apple.com>
Date: Thu, 24 Oct 2024 17:50:23 -0700
Subject: [PATCH] [ObjC] Insert method parameters in scope as they are parsed
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.
rdar://138596211
---
clang/include/clang/Sema/SemaObjC.h | 6 +-
clang/lib/Parse/ParseObjc.cpp | 10 ++-
clang/lib/Sema/SemaDeclObjC.cpp | 112 ++++++++++++++--------------
3 files changed, 69 insertions(+), 59 deletions(-)
diff --git a/clang/include/clang/Sema/SemaObjC.h b/clang/include/clang/Sema/SemaObjC.h
index 1332eb4f4d4233..791a7f45b832f7 100644
--- a/clang/include/clang/Sema/SemaObjC.h
+++ b/clang/include/clang/Sema/SemaObjC.h
@@ -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 -.
@@ -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);
diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp
index 28ccd3061f8433..e69fa152481982 100644
--- a/clang/lib/Parse/ParseObjc.cpp
+++ b/clang/lib/Parse/ParseObjc.cpp
@@ -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);
@@ -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);
@@ -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;
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp
index 78acfeddb78639..3b19c9b21c257f 100644
--- a/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/clang/lib/Sema/SemaDeclObjC.cpp
@@ -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) {
@@ -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);
}
More information about the cfe-commits
mailing list