r190476 - The cleanup attribute no longer uses an unresolved, simple identifier as its argument. Instead, it takes an expression that is fully resolved.

Aaron Ballman aaron at aaronballman.com
Tue Sep 10 18:37:41 PDT 2013


Author: aaronballman
Date: Tue Sep 10 20:37:41 2013
New Revision: 190476

URL: http://llvm.org/viewvc/llvm-project?rev=190476&view=rev
Log:
The cleanup attribute no longer uses an unresolved, simple identifier as its argument.  Instead, it takes an expression that is fully resolved.

Added:
    cfe/trunk/test/CodeGenCXX/attr-cleanup.cpp
    cfe/trunk/test/SemaCXX/attr-cleanup-gcc.cpp
    cfe/trunk/test/SemaCXX/attr-cleanup.cpp
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaDeclAttr.cpp
    cfe/trunk/test/Sema/attr-cleanup.c
    cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=190476&r1=190475&r2=190476&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Sep 10 20:37:41 2013
@@ -2350,10 +2350,14 @@ def err_attribute_sentinel_less_than_zer
   "'sentinel' parameter 1 less than zero">;
 def err_attribute_sentinel_not_zero_or_one : Error<
   "'sentinel' parameter 2 not 0 or 1">;
+def warn_cleanup_ext : Warning<
+  "GCC does not allow the 'cleanup' attribute argument to be anything other "
+  "than a simple identifier">, 
+  InGroup<GccCompat>;
 def err_attribute_cleanup_arg_not_found : Error<
   "'cleanup' argument %0 not found">;
 def err_attribute_cleanup_arg_not_function : Error<
-  "'cleanup' argument %0 is not a function">;
+  "'cleanup' argument %select{|%1 }0is not a function">;
 def err_attribute_cleanup_func_must_take_one_arg : Error<
   "'cleanup' function %0 must take 1 parameter">;
 def err_attribute_cleanup_func_arg_incompatible_type : Error<

Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=190476&r1=190475&r2=190476&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Tue Sep 10 20:37:41 2013
@@ -2831,40 +2831,44 @@ static void handlePureAttr(Sema &S, Decl
 }
 
 static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) {
-  if (!Attr.isArgIdent(0)) {
-    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
-      << Attr.getName() << 1;
-    return;
-  }
-  
   VarDecl *VD = dyn_cast<VarDecl>(D);
-
   if (!VD || !VD->hasLocalStorage()) {
-    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "cleanup";
-    return;
-  }
-
-  IdentifierLoc *IL = Attr.getArgAsIdent(0);
-
-  // Look up the function
-  // FIXME: Lookup probably isn't looking in the right place
-  NamedDecl *CleanupDecl
-    = S.LookupSingleName(S.TUScope, IL->Ident, IL->Loc,
-                         Sema::LookupOrdinaryName);
-  if (!CleanupDecl) {
-    S.Diag(IL->Loc, diag::err_attribute_cleanup_arg_not_found) << IL->Ident;
+    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
     return;
   }
 
-  FunctionDecl *FD = dyn_cast<FunctionDecl>(CleanupDecl);
-  if (!FD) {
-    S.Diag(IL->Loc, diag::err_attribute_cleanup_arg_not_function) << IL->Ident;
+  Expr *E = Attr.getArgAsExpr(0);
+  SourceLocation Loc = E->getExprLoc();
+  FunctionDecl *FD = 0;
+  DeclarationNameInfo NI;
+
+  // gcc only allows for simple identifiers. Since we support more than gcc, we
+  // will warn the user.
+  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+    if (DRE->hasQualifier())
+      S.Diag(Loc, diag::warn_cleanup_ext);
+    FD = dyn_cast<FunctionDecl>(DRE->getDecl());
+    NI = DRE->getNameInfo();
+    if (!FD) {
+      S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 1
+        << NI.getName();
+      return;
+    }
+  } else if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
+    if (ULE->hasExplicitTemplateArgs())
+      S.Diag(Loc, diag::warn_cleanup_ext);
+
+    // This will diagnose the case where the function cannot be found.
+    FD = S.ResolveSingleFunctionTemplateSpecialization(ULE, true);
+    NI = ULE->getNameInfo();
+  } else {
+    S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 0;
     return;
   }
 
   if (FD->getNumParams() != 1) {
-    S.Diag(IL->Loc, diag::err_attribute_cleanup_func_must_take_one_arg)
-      << IL->Ident;
+    S.Diag(Loc, diag::err_attribute_cleanup_func_must_take_one_arg)
+      << NI.getName();
     return;
   }
 
@@ -2874,16 +2878,14 @@ static void handleCleanupAttr(Sema &S, D
   QualType ParamTy = FD->getParamDecl(0)->getType();
   if (S.CheckAssignmentConstraints(FD->getParamDecl(0)->getLocation(),
                                    ParamTy, Ty) != Sema::Compatible) {
-    S.Diag(IL->Loc, diag::err_attribute_cleanup_func_arg_incompatible_type) <<
-      IL->Ident << ParamTy << Ty;
+    S.Diag(Loc, diag::err_attribute_cleanup_func_arg_incompatible_type)
+      << NI.getName() << ParamTy << Ty;
     return;
   }
 
   D->addAttr(::new (S.Context)
              CleanupAttr(Attr.getRange(), S.Context, FD,
                          Attr.getAttributeSpellingListIndex()));
-  S.MarkFunctionReferenced(IL->Loc, FD);
-  S.DiagnoseUseOfDecl(FD, IL->Loc);
 }
 
 /// Handle __attribute__((format_arg((idx)))) attribute based on

Added: cfe/trunk/test/CodeGenCXX/attr-cleanup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/attr-cleanup.cpp?rev=190476&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/attr-cleanup.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/attr-cleanup.cpp Tue Sep 10 20:37:41 2013
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+
+namespace N {
+  void free(void *i) {}
+}
+
+int main(void) {
+  // CHECK: call void @_ZN1N4freeEPv(i8* %0)
+  void *fp __attribute__((cleanup(N::free)));
+  return 0;
+}

Modified: cfe/trunk/test/Sema/attr-cleanup.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/attr-cleanup.c?rev=190476&r1=190475&r2=190476&view=diff
==============================================================================
--- cfe/trunk/test/Sema/attr-cleanup.c (original)
+++ cfe/trunk/test/Sema/attr-cleanup.c Tue Sep 10 20:37:41 2013
@@ -2,18 +2,18 @@
 
 void c1(int *a);
 
-extern int g1 __attribute((cleanup(c1))); // expected-warning {{cleanup attribute ignored}}
-int g2 __attribute((cleanup(c1))); // expected-warning {{cleanup attribute ignored}}
-static int g3 __attribute((cleanup(c1))); // expected-warning {{cleanup attribute ignored}}
+extern int g1 __attribute((cleanup(c1))); // expected-warning {{'cleanup' attribute ignored}}
+int g2 __attribute((cleanup(c1))); // expected-warning {{'cleanup' attribute ignored}}
+static int g3 __attribute((cleanup(c1))); // expected-warning {{'cleanup' attribute ignored}}
 
 void t1()
 {
     int v1 __attribute((cleanup)); // expected-error {{'cleanup' attribute takes one argument}}
     int v2 __attribute((cleanup(1, 2))); // expected-error {{'cleanup' attribute takes one argument}}
 
-    static int v3 __attribute((cleanup(c1))); // expected-warning {{cleanup attribute ignored}}
+    static int v3 __attribute((cleanup(c1))); // expected-warning {{'cleanup' attribute ignored}}
 
-    int v4 __attribute((cleanup(h))); // expected-error {{'cleanup' argument 'h' not found}}
+    int v4 __attribute((cleanup(h))); // expected-error {{use of undeclared identifier 'h'}}
 
     int v5 __attribute((cleanup(c1)));
     int v6 __attribute((cleanup(v3))); // expected-error {{'cleanup' argument 'v3' is not a function}}
@@ -42,3 +42,7 @@ void c5(void*) __attribute__((deprecated
 void t5() {
   int i __attribute__((cleanup(c5)));  // expected-warning {{'c5' is deprecated}}
 }
+
+void t6(void) {
+  int i __attribute__((cleanup((void *)0)));  // expected-error {{'cleanup' argument is not a function}}
+}

Added: cfe/trunk/test/SemaCXX/attr-cleanup-gcc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/attr-cleanup-gcc.cpp?rev=190476&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/attr-cleanup-gcc.cpp (added)
+++ cfe/trunk/test/SemaCXX/attr-cleanup-gcc.cpp Tue Sep 10 20:37:41 2013
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 %s -verify -fsyntax-only -Wgcc-compat
+
+namespace N {
+  void c1(int *a) {}
+}
+
+void c2(int *a) {}
+
+template <typename Ty>
+void c3(Ty *a) {}
+
+void t3() {
+  int v1 __attribute__((cleanup(N::c1)));  // expected-warning  {{GCC does not allow the 'cleanup' attribute argument to be anything other than a simple identifier}}
+  int v2 __attribute__((cleanup(c2)));
+  int v3 __attribute__((cleanup(c3<int>)));  // expected-warning  {{GCC does not allow the 'cleanup' attribute argument to be anything other than a simple identifier}}
+}

Added: cfe/trunk/test/SemaCXX/attr-cleanup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/attr-cleanup.cpp?rev=190476&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/attr-cleanup.cpp (added)
+++ cfe/trunk/test/SemaCXX/attr-cleanup.cpp Tue Sep 10 20:37:41 2013
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 %s -verify -fsyntax-only -Wno-gcc-compat
+
+namespace N {
+  void c1(int *a) {}
+}
+
+void t1() {
+  int v1 __attribute__((cleanup(N::c1)));
+  int v2 __attribute__((cleanup(N::c2)));  // expected-error {{no member named 'c2' in namespace 'N'}}
+}

Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=190476&r1=190475&r2=190476&view=diff
==============================================================================
--- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original)
+++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Tue Sep 10 20:37:41 2013
@@ -1069,6 +1069,7 @@ void EmitClangAttrExprArgsList(RecordKee
           .Case("AlignedArgument", true)
           .Case("BoolArgument", true)
           .Case("DefaultIntArgument", true)
+          .Case("FunctionArgument", true)
           .Case("IntArgument", true)
           .Case("ExprArgument", true)
           .Case("StringArgument", true)





More information about the cfe-commits mailing list