Skip to content

Commit a84de8a

Browse files
committed
Fix for cleaup attribute and sets base for fixing other type dependent
attributes Fixes #129631
1 parent f2ed002 commit a84de8a

File tree

5 files changed

+60
-10
lines changed

5 files changed

+60
-10
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,7 @@ Bug Fixes to Attribute Support
486486
- Fixes crashes or missing diagnostics with the `device_kernel` attribute. (#GH161905)
487487
- Fix handling of parameter indexes when an attribute is applied to a C++23 explicit object member function.
488488
- Fixed several false positives and false negatives in function effect (`nonblocking`) analysis. (#GH166078) (#GH166101) (#GH166110)
489+
- Fix ``cleanup`` attribute by delaying type checks after the type is deduced. (#GH129631)
489490

490491
Bug Fixes to C++ Support
491492
^^^^^^^^^^^^^^^^^^^^^^^^

clang/include/clang/Sema/Sema.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4456,6 +4456,10 @@ class Sema final : public SemaBase {
44564456
NamedDecl *New, Decl *Old,
44574457
AvailabilityMergeKind AMK = AvailabilityMergeKind::Redeclaration);
44584458

4459+
/// CheckAttributesOnDeducedType - Calls Sema functions for attributes that
4460+
/// requires the type to be deduced.
4461+
void CheckAttributesOnDeducedType(Expr *E, Decl *D);
4462+
44594463
/// MergeTypedefNameDecl - We just parsed a typedef 'New' which has the
44604464
/// same name and scope as a previous declaration 'Old'. Figure out
44614465
/// how to resolve this situation, merging decls or emitting
@@ -15468,6 +15472,8 @@ class Sema final : public SemaBase {
1546815472
std::optional<FunctionEffectMode>
1546915473
ActOnEffectExpression(Expr *CondExpr, StringRef AttributeName);
1547015474

15475+
void ActOnCleanupAttr(Expr *E, Decl *D, const Attr *A);
15476+
1547115477
private:
1547215478
/// The implementation of RequireCompleteType
1547315479
bool RequireCompleteTypeImpl(SourceLocation Loc, QualType T,

clang/lib/Sema/SemaDecl.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3355,6 +3355,21 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old,
33553355
if (!foundAny) New->dropAttrs();
33563356
}
33573357

3358+
void Sema::CheckAttributesOnDeducedType(Expr *E, Decl *D) {
3359+
if (!D->hasAttrs())
3360+
return;
3361+
3362+
for (const Attr *A : D->getAttrs()) {
3363+
switch (A->getKind()) {
3364+
case attr::Cleanup:
3365+
ActOnCleanupAttr(E, D, A);
3366+
break;
3367+
default:
3368+
continue;
3369+
}
3370+
}
3371+
}
3372+
33583373
// Returns the number of added attributes.
33593374
template <class T>
33603375
static unsigned propagateAttribute(ParmVarDecl *To, const ParmVarDecl *From,
@@ -13809,6 +13824,8 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
1380913824
return;
1381013825
}
1381113826

13827+
this->CheckAttributesOnDeducedType(Init, RealDecl);
13828+
1381213829
// dllimport cannot be used on variable definitions.
1381313830
if (VDecl->hasAttr<DLLImportAttr>() && !VDecl->isStaticDataMember()) {
1381413831
Diag(VDecl->getLocation(), diag::err_attribute_dllimport_data_definition);
@@ -14599,6 +14616,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
1459914616
Var->setInit(RecoveryExpr.get());
1460014617
}
1460114618

14619+
this->CheckAttributesOnDeducedType(Init.get(), RealDecl);
1460214620
CheckCompleteVariableDeclaration(Var);
1460314621
}
1460414622
}

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3511,16 +3511,6 @@ static void handleCleanupAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
35113511
return;
35123512
}
35133513

3514-
// We're currently more strict than GCC about what function types we accept.
3515-
// If this ever proves to be a problem it should be easy to fix.
3516-
QualType Ty = S.Context.getPointerType(cast<VarDecl>(D)->getType());
3517-
QualType ParamTy = FD->getParamDecl(0)->getType();
3518-
if (!S.IsAssignConvertCompatible(S.CheckAssignmentConstraints(
3519-
FD->getParamDecl(0)->getLocation(), ParamTy, Ty))) {
3520-
S.Diag(Loc, diag::err_attribute_cleanup_func_arg_incompatible_type)
3521-
<< NI.getName() << ParamTy << Ty;
3522-
return;
3523-
}
35243514
VarDecl *VD = cast<VarDecl>(D);
35253515
// Create a reference to the variable declaration. This is a fake/dummy
35263516
// reference.
@@ -8311,3 +8301,27 @@ void Sema::redelayDiagnostics(DelayedDiagnosticPool &pool) {
83118301
assert(curPool && "re-emitting in undelayed context not supported");
83128302
curPool->steal(pool);
83138303
}
8304+
8305+
void Sema::ActOnCleanupAttr(Expr *E, Decl *D, const Attr *A) {
8306+
FunctionDecl *FD = nullptr;
8307+
DeclarationNameInfo NI;
8308+
CleanupAttr *Attr = D->getAttr<CleanupAttr>();
8309+
8310+
// Obtains the FunctionDecl that was found when handling the attribute
8311+
// earlier.
8312+
FD = Attr->getFunctionDecl();
8313+
NI = FD->getNameInfo();
8314+
8315+
// We're currently more strict than GCC about what function types we accept.
8316+
// If this ever proves to be a problem it should be easy to fix.
8317+
QualType Ty = this->Context.getPointerType(cast<VarDecl>(D)->getType());
8318+
QualType ParamTy = FD->getParamDecl(0)->getType();
8319+
if (!this->IsAssignConvertCompatible(this->CheckAssignmentConstraints(
8320+
FD->getParamDecl(0)->getLocation(), ParamTy, Ty))) {
8321+
this->Diag(Attr->getArgLoc(),
8322+
diag::err_attribute_cleanup_func_arg_incompatible_type)
8323+
<< NI.getName() << ParamTy << Ty;
8324+
D->dropAttr<CleanupAttr>();
8325+
return;
8326+
}
8327+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %clang_cc1 -std=c23 -fsyntax-only -verify %s
2+
3+
// #GH129631-CleanupAttr
4+
int open() { return 0; }
5+
void close(typeof(open()) *) {}
6+
7+
void cleanup_attr() {
8+
int fd_int [[gnu::cleanup(close)]] = open();
9+
auto fd_auto [[gnu::cleanup(close)]] = open();
10+
float fd_invalid [[gnu::cleanup(close)]] = open(); // expected-error {{'cleanup' function 'close' parameter has type 'typeof (open()) *' (aka 'int *') which is incompatible with type 'float *'}}
11+
}

0 commit comments

Comments
 (0)