[cfe-commits] r64414 - in /cfe/trunk: include/clang/AST/Attr.h include/clang/Basic/DiagnosticSemaKinds.def lib/Sema/SemaDecl.cpp test/Sema/overloadable.c

Douglas Gregor dgregor at apple.com
Thu Feb 12 16:26:38 PST 2009


Author: dgregor
Date: Thu Feb 12 18:26:38 2009
New Revision: 64414

URL: http://llvm.org/viewvc/llvm-project?rev=64414&view=rev
Log:
Tighten checking of the "overloadable" attribute. If any function by a
given name in a given scope is marked as "overloadable", every
function declaration and definition with that same name and in that
same scope needs to have the "overloadable" attribute. Essentially,
the "overloadable" attribute is not part of attribute merging, so it
must be specified even for redeclarations. This keeps users from
trying to be too sneaky for their own good:

  double sin(double) __attribute__((overloadable)); // too sneaky
  #include <math.h>

Previously, this would have made "sin" overloadable, and therefore
given it a mangled name. Now, we get an error inside math.h when we
see a (re)declaration of "sin" that doesn't have the "overloadable"
attribute.


Modified:
    cfe/trunk/include/clang/AST/Attr.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/Sema/overloadable.c

Modified: cfe/trunk/include/clang/AST/Attr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Attr.h?rev=64414&r1=64413&r2=64414&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Attr.h (original)
+++ cfe/trunk/include/clang/AST/Attr.h Thu Feb 12 18:26:38 2009
@@ -70,6 +70,10 @@
     delete Next;
   }
 
+  /// \brief Whether this attribute should be merged to new
+  /// declarations.
+  virtual bool isMerged() const { return true; }
+
   Kind getKind() const { return AttrKind; }
 
   Attr *getNext() { return Next; }
@@ -449,6 +453,8 @@
 public:
   OverloadableAttr() : Attr(Overloadable) { }
 
+  virtual bool isMerged() const { return false; }
+
   static bool classof(const Attr *A) { return A->getKind() == Overloadable; }
   static bool classof(const OverloadableAttr *) { return true; }
 };

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def?rev=64414&r1=64413&r2=64414&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def Thu Feb 12 18:26:38 2009
@@ -396,7 +396,7 @@
 DIAG(err_attribute_overloadable_not_function, ERROR,
      "'overloadable' attribute can only be applied to a function")
 DIAG(err_attribute_overloadable_missing, ERROR,
-     "overloaded function %0 must have the 'overloadable' attribute")
+     "%select{overloaded function|redeclaration of}0 %1 must have the 'overloadable' attribute")
 DIAG(note_attribute_overloadable_prev_overload, NOTE,
      "previous overload of function is here")
 

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=64414&r1=64413&r2=64414&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Feb 12 18:26:38 2009
@@ -446,15 +446,15 @@
   Attr *attr = const_cast<Attr*>(Old->getAttrs()), *tmp;
 
   while (attr) {
-     tmp = attr;
-     attr = attr->getNext();
+    tmp = attr;
+    attr = attr->getNext();
 
-    if (!DeclHasAttr(New, tmp)) {
-       tmp->setInherited(true);
-       New->addAttr(tmp);
+    if (!DeclHasAttr(New, tmp) && tmp->isMerged()) {
+      tmp->setInherited(true);
+      New->addAttr(tmp);
     } else {
-       tmp->setNext(0);
-       delete(tmp);
+      tmp->setNext(0);
+      delete(tmp);
     }
   }
 
@@ -1666,6 +1666,11 @@
     // there's no more work to do here; we'll just add the new
     // function to the scope.
     OverloadedFunctionDecl::function_iterator MatchedDecl;
+
+    if (!getLangOptions().CPlusPlus &&
+        AllowOverloadingOfFunction(PrevDecl, Context))
+      OverloadableAttrRequired = true;
+
     if (!AllowOverloadingOfFunction(PrevDecl, Context) || 
         !IsOverload(NewFD, PrevDecl, MatchedDecl)) {
       Decl *OldDecl = PrevDecl;
@@ -1693,12 +1698,6 @@
         }
       }
     }
-
-    // If we're in C, this new declaration better have the
-    // "overloadable" attribute on it.
-    if (!getLangOptions().CPlusPlus && 
-        PrevDecl->getAttr<OverloadableAttr>())
-      OverloadableAttrRequired = true;
   }
 
   if (D.getCXXScopeSpec().isSet() &&
@@ -1743,7 +1742,7 @@
     // If a function name is overloadable in C, then every function
     // with that name must be marked "overloadable".
     Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing)
-      << NewFD;
+      << Redeclaration << NewFD;
     if (PrevDecl)
       Diag(PrevDecl->getLocation(), 
            diag::note_attribute_overloadable_prev_overload);

Modified: cfe/trunk/test/Sema/overloadable.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/overloadable.c?rev=64414&r1=64413&r2=64414&view=diff

==============================================================================
--- cfe/trunk/test/Sema/overloadable.c (original)
+++ cfe/trunk/test/Sema/overloadable.c Thu Feb 12 18:26:38 2009
@@ -2,9 +2,10 @@
 
 int var __attribute__((overloadable)); // expected-error{{'overloadable' attribute can only be applied to a function}}
 
-int *f(int) __attribute__((overloadable)); // expected-note{{previous overload of function is here}}
+int *f(int) __attribute__((overloadable)); // expected-note 2{{previous overload of function is here}}
 float *f(float); // expected-error{{overloaded function 'f' must have the 'overloadable' attribute}}
-int *f(int); // expected-note{{previous declaration is here}}
+int *f(int); // expected-error{{redeclaration of 'f' must have the 'overloadable' attribute}} \
+             // expected-note{{previous declaration is here}}
 double *f(double) __attribute__((overloadable)); // okay, new
 
 void test_f(int iv, float fv, double dv) {
@@ -35,3 +36,5 @@
 }
 
 double *f(int) __attribute__((overloadable)); // expected-error{{conflicting types for 'f'}}
+
+





More information about the cfe-commits mailing list