]> granicus.if.org Git - clang/commitdiff
Don't allow calls to functions marked "unavailable". There's more work
authorDouglas Gregor <dgregor@apple.com>
Wed, 18 Feb 2009 06:34:51 +0000 (06:34 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 18 Feb 2009 06:34:51 +0000 (06:34 +0000)
to do in this area, since there are other places that reference
FunctionDecls.

Don't allow "overloadable" functions (in C) to be declared without a
prototype.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64897 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.def
lib/Sema/SemaDecl.cpp
lib/Sema/SemaExpr.cpp
test/Sema/overloadable.c
test/SemaCXX/attr-unavailable.cpp [new file with mode: 0644]

index 19d9b65ffaad4bcfe3e8bc6cf759f028bc90eefb..16692412dcafecbab108d659322b5d01aca1d174 100644 (file)
@@ -418,6 +418,8 @@ DIAG(err_attribute_overloadable_missing, ERROR,
      "%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")
+DIAG(err_attribute_overloadable_no_prototype, ERROR,
+     "'overloadable' function %0 must have a prototype")
 
 // Function Parameter Semantic Analysis.
 DIAG(err_param_with_void_type, ERROR,
@@ -1051,6 +1053,10 @@ DIAG(err_typecheck_call_too_few_args, ERROR,
      "too few arguments to %select{function|block|method}0 call")
 DIAG(err_typecheck_call_too_many_args, ERROR,
      "too many arguments to %select{function|block|method}0 call")
+DIAG(err_call_deleted_function, ERROR,
+     "call to function %1 that has been intentionally %select{deleted|made unavailable}0 ")
+DIAG(note_deleted_function_here, NOTE,
+     "%select{deleted|unavailable}0 function is declared here")
 DIAG(warn_cannot_pass_non_pod_arg_to_vararg, WARNING,
      "cannot pass object of non-POD type %0 through variadic "
      "%select{function|block|method}1; call will abort at runtime")
index 55e2a9247621ecba37fe9a6ebe2fce71b3db3f5e..0543b0adc67eb8ea5e877e39eca326c869ed0767 100644 (file)
@@ -1763,11 +1763,27 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
     OverloadedFunctionDecl::function_iterator MatchedDecl;
 
     if (!getLangOptions().CPlusPlus &&
-        AllowOverloadingOfFunction(PrevDecl, Context))
+        AllowOverloadingOfFunction(PrevDecl, Context)) {
       OverloadableAttrRequired = true;
 
-    if (!AllowOverloadingOfFunction(PrevDecl, Context) || 
-        !IsOverload(NewFD, PrevDecl, MatchedDecl)) {
+      // Functions marked "overloadable" must have a prototype (that
+      // we can't get through declaration merging).
+      if (!R->getAsFunctionTypeProto()) {
+        Diag(NewFD->getLocation(), diag::err_attribute_overloadable_no_prototype)
+          << NewFD;
+        InvalidDecl = true;
+        Redeclaration = true;
+
+        // Turn this into a variadic function with no parameters.
+        R = Context.getFunctionType(R->getAsFunctionType()->getResultType(),
+                                    0, 0, true, 0);
+        NewFD->setType(R);
+      }
+    }
+
+    if (PrevDecl && 
+        (!AllowOverloadingOfFunction(PrevDecl, Context) || 
+         !IsOverload(NewFD, PrevDecl, MatchedDecl))) {
       Redeclaration = true;
       Decl *OldDecl = PrevDecl;
 
index c0b61bf8d7c7df469e75e39c6a36b88fdc1a3773..48f338e475dfeb84329a97dd985027a54fe83d8c 100644 (file)
@@ -2032,13 +2032,21 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
 
   // Make the call expr early, before semantic checks.  This guarantees cleanup
   // of arguments and function on error.
-  // FIXME: Except that llvm::OwningPtr uses delete, when it really must be
-  // Destroy(), or nothing gets cleaned up.
   ExprOwningPtr<CallExpr> TheCall(this, new (Context) CallExpr(Context, Fn,
                                                                Args, NumArgs,
                                                                Context.BoolTy,
                                                                RParenLoc));
 
+  // Check for a call to a (FIXME: deleted) or unavailable function.
+  if (FDecl && FDecl->getAttr<UnavailableAttr>()) {
+    Diag(Fn->getSourceRange().getBegin(), diag::err_call_deleted_function)
+      << FDecl->getAttr<UnavailableAttr>() << FDecl->getDeclName()
+      << Fn->getSourceRange();
+    Diag(FDecl->getLocation(), diag::note_deleted_function_here)
+      << FDecl->getAttr<UnavailableAttr>();
+    return ExprError();
+  }
+
   const FunctionType *FuncT;
   if (!Fn->getType()->isBlockPointerType()) {
     // C99 6.5.2.2p1 - "The expression that denotes the called function shall
index afac741070923820dbf2b773a42b595a1c7ba715..136f8e93d7e89eb8ba2bb828089c25314479cc9a 100644 (file)
@@ -37,4 +37,14 @@ void test_struct(struct X x, struct Y y) {
 
 double *f(int) __attribute__((overloadable)); // expected-error{{conflicting types for 'f'}}
 
+double promote(float) __attribute__((__overloadable__));
+double promote(double) __attribute__((__overloadable__));
+long double promote(long double) __attribute__((__overloadable__));
+
+void promote() __attribute__((__overloadable__)); // expected-error{{'overloadable' function 'promote' must have a prototype}}
+
+void test_promote(short* sp) {
+  promote(1.0);
+}
+
 
diff --git a/test/SemaCXX/attr-unavailable.cpp b/test/SemaCXX/attr-unavailable.cpp
new file mode 100644 (file)
index 0000000..140008a
--- /dev/null
@@ -0,0 +1,11 @@
+// RUN: clang -fsyntax-only -verify %s
+
+int &foo(int);
+double &foo(double);
+void foo(...) __attribute__((__unavailable__)); // expected-note{{unavailable function is declared here}}
+
+void test_foo(short* sp) {
+  int &ir = foo(1);
+  double &dr = foo(1.0);
+  foo(sp); // expected-error{{call to function 'foo' that has been intentionally made unavailable}}
+}