Skip to content

Commit e65806e

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

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
@@ -447,6 +447,7 @@ Bug Fixes to Attribute Support
447447
- Using ``[[gnu::cleanup(some_func)]]`` where some_func is annotated with
448448
``[[gnu::error("some error")]]`` now correctly triggers an error. (#GH146520)
449449
- Fix a crash when the function name is empty in the `swift_name` attribute. (#GH157075)
450+
- Fix ``cleanup`` attribute by delaying type checks after the type is deduced. (#GH129631)
450451

451452
Bug Fixes to C++ Support
452453
^^^^^^^^^^^^^^^^^^^^^^^^

clang/include/clang/Sema/Sema.h

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

4468+
/// CheckAttributesOnDeducedType - Calls Sema functions for attributes that
4469+
/// requires the type to be deduced.
4470+
void CheckAttributesOnDeducedType(Expr *E, Decl *D);
4471+
44684472
/// MergeTypedefNameDecl - We just parsed a typedef 'New' which has the
44694473
/// same name and scope as a previous declaration 'Old'. Figure out
44704474
/// how to resolve this situation, merging decls or emitting
@@ -15483,6 +15487,8 @@ class Sema final : public SemaBase {
1548315487
std::optional<FunctionEffectMode>
1548415488
ActOnEffectExpression(Expr *CondExpr, StringRef AttributeName);
1548515489

15490+
void ActOnCleanupAttr(Expr *E, Decl *D, const Attr *A);
15491+
1548615492
private:
1548715493
/// The implementation of RequireCompleteType
1548815494
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
@@ -3354,6 +3354,21 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old,
33543354
if (!foundAny) New->dropAttrs();
33553355
}
33563356

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

13815+
this->CheckAttributesOnDeducedType(Init, RealDecl);
13816+
1380013817
// dllimport cannot be used on variable definitions.
1380113818
if (VDecl->hasAttr<DLLImportAttr>() && !VDecl->isStaticDataMember()) {
1380213819
Diag(VDecl->getLocation(), diag::err_attribute_dllimport_data_definition);
@@ -14587,6 +14604,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
1458714604
Var->setInit(RecoveryExpr.get());
1458814605
}
1458914606

14607+
this->CheckAttributesOnDeducedType(Init.get(), RealDecl);
1459014608
CheckCompleteVariableDeclaration(Var);
1459114609
}
1459214610
}

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.
@@ -8291,3 +8281,27 @@ void Sema::redelayDiagnostics(DelayedDiagnosticPool &pool) {
82918281
assert(curPool && "re-emitting in undelayed context not supported");
82928282
curPool->steal(pool);
82938283
}
8284+
8285+
void Sema::ActOnCleanupAttr(Expr *E, Decl *D, const Attr *A) {
8286+
FunctionDecl *FD = nullptr;
8287+
DeclarationNameInfo NI;
8288+
CleanupAttr *Attr = D->getAttr<CleanupAttr>();
8289+
8290+
// Obtains the FunctionDecl that was found when handling the attribute
8291+
// earlier.
8292+
FD = Attr->getFunctionDecl();
8293+
NI = FD->getNameInfo();
8294+
8295+
// We're currently more strict than GCC about what function types we accept.
8296+
// If this ever proves to be a problem it should be easy to fix.
8297+
QualType Ty = this->Context.getPointerType(cast<VarDecl>(D)->getType());
8298+
QualType ParamTy = FD->getParamDecl(0)->getType();
8299+
if (!this->IsAssignConvertCompatible(this->CheckAssignmentConstraints(
8300+
FD->getParamDecl(0)->getLocation(), ParamTy, Ty))) {
8301+
this->Diag(Attr->getArgLoc(),
8302+
diag::err_attribute_cleanup_func_arg_incompatible_type)
8303+
<< NI.getName() << ParamTy << Ty;
8304+
D->dropAttr<CleanupAttr>();
8305+
return;
8306+
}
8307+
}
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)