From 723f55d6975d4970c00126369c7360d1a665ac94 Mon Sep 17 00:00:00 2001 From: Anders Carlsson <andersca@mac.com> Date: Sat, 7 Feb 2009 23:16:50 +0000 Subject: [PATCH] Improve Sema of the cleanup attribute somewhat. llvm-svn: 64047 --- .../clang/Basic/DiagnosticSemaKinds.def | 4 +++- clang/lib/Sema/SemaDeclAttr.cpp | 23 +++++++++++++++---- clang/test/Sema/attr-cleanup.c | 4 +++- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.def b/clang/include/clang/Basic/DiagnosticSemaKinds.def index a18ed966f3b9..539b659d63c7 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.def +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.def @@ -385,8 +385,10 @@ DIAG(err_attribute_cleanup_arg_not_found, ERROR, "'cleanup' argument %0 not found") DIAG(err_attribute_cleanup_arg_not_function, ERROR, "'cleanup' argument %0 is not a function") -DIAG(err_attribute_cleanup_arg_must_take_one_arg, ERROR, +DIAG(err_attribute_cleanup_func_must_take_one_arg, ERROR, "'cleanup' function %0 must take 1 parameter") +DIAG(err_attribute_cleanup_func_arg_incompatible_type, ERROR, + "'cleanup' function %0 parameter has type %1, expected type %2") // Clang-Specific Attributes DIAG(err_attribute_iboutlet_non_ivar, ERROR, diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 231efc7563ba..2a6da06f7105 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -847,6 +847,10 @@ static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) { } static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) { + // Match gcc which ignores cleanup attrs when compiling C++. + if (S.getLangOptions().CPlusPlus) + return; + if (!Attr.getParameterName()) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; return; @@ -868,26 +872,35 @@ static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) { NamedDecl *CleanupDecl = S.LookupName(S.TUScope, Attr.getParameterName(), Sema::LookupOrdinaryName); if (!CleanupDecl) { - S.Diag(Attr.getLoc(), diag::err_attribute_cleanup_arg_not_found) << + S.Diag(Attr.getLoc(), diag::err_attribute_cleanup_arg_not_found) << Attr.getParameterName(); return; } FunctionDecl *FD = dyn_cast<FunctionDecl>(CleanupDecl); if (!FD) { - S.Diag(Attr.getLoc(), diag::err_attribute_cleanup_arg_not_function) << + S.Diag(Attr.getLoc(), diag::err_attribute_cleanup_arg_not_function) << Attr.getParameterName(); return; } - // FIXME: This needs to work with C++ overloading. - // FIXME: This should verify that the function type is compatible if (FD->getNumParams() != 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_cleanup_arg_must_take_one_arg)<< + S.Diag(Attr.getLoc(), diag::err_attribute_cleanup_func_must_take_one_arg) << Attr.getParameterName(); return; } + // We're currently more strict than GCC about what function types we accept. + // If this ever proves to be a problem it should be easy to fix. + QualType Ty = S.Context.getPointerType(VD->getType()); + QualType ParamTy = FD->getParamDecl(0)->getType(); + if (Ty != ParamTy) { + S.Diag(Attr.getLoc(), + diag::err_attribute_cleanup_func_arg_incompatible_type) << + Attr.getParameterName() << ParamTy << Ty; + return; + } + d->addAttr(new CleanupAttr(FD)); } diff --git a/clang/test/Sema/attr-cleanup.c b/clang/test/Sema/attr-cleanup.c index c58d17b7ef4b..e5dd3a26d8af 100644 --- a/clang/test/Sema/attr-cleanup.c +++ b/clang/test/Sema/attr-cleanup.c @@ -24,8 +24,10 @@ struct s { }; void c2(); +void c3(struct s a); void t2() { int v1 __attribute__((cleanup(c2))); // expected-error {{'cleanup' function 'c2' must take 1 parameter}} -} \ No newline at end of file + int v2 __attribute__((cleanup(c3))); // expected-error {{'cleanup' function 'c3' parameter has type 'struct s', expected type 'int *'}} +}