diff options
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.def | 4 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 23 | ||||
-rw-r--r-- | test/Sema/attr-cleanup.c | 4 |
3 files changed, 24 insertions, 7 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.def b/include/clang/Basic/DiagnosticSemaKinds.def index a18ed966f3..539b659d63 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.def +++ b/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/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 231efc7563..2a6da06f71 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/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/test/Sema/attr-cleanup.c b/test/Sema/attr-cleanup.c index c58d17b7ef..e5dd3a26d8 100644 --- a/test/Sema/attr-cleanup.c +++ b/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 *'}} +} |