[cfe-commits] r64897 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.def lib/Sema/SemaDecl.cpp lib/Sema/SemaExpr.cpp test/Sema/overloadable.c test/SemaCXX/attr-unavailable.cpp
Douglas Gregor
dgregor at apple.com
Tue Feb 17 22:34:51 PST 2009
Author: dgregor
Date: Wed Feb 18 00:34:51 2009
New Revision: 64897
URL: http://llvm.org/viewvc/llvm-project?rev=64897&view=rev
Log:
Don't allow calls to functions marked "unavailable". There's more work
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.
Added:
cfe/trunk/test/SemaCXX/attr-unavailable.cpp
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/test/Sema/overloadable.c
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def?rev=64897&r1=64896&r2=64897&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def Wed Feb 18 00:34:51 2009
@@ -418,6 +418,8 @@
"%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 @@
"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")
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=64897&r1=64896&r2=64897&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Feb 18 00:34:51 2009
@@ -1763,11 +1763,27 @@
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;
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=64897&r1=64896&r2=64897&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Feb 18 00:34:51 2009
@@ -2032,13 +2032,21 @@
// 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
Modified: cfe/trunk/test/Sema/overloadable.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/overloadable.c?rev=64897&r1=64896&r2=64897&view=diff
==============================================================================
--- cfe/trunk/test/Sema/overloadable.c (original)
+++ cfe/trunk/test/Sema/overloadable.c Wed Feb 18 00:34:51 2009
@@ -37,4 +37,14 @@
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);
+}
+
Added: cfe/trunk/test/SemaCXX/attr-unavailable.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/attr-unavailable.cpp?rev=64897&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/attr-unavailable.cpp (added)
+++ cfe/trunk/test/SemaCXX/attr-unavailable.cpp Wed Feb 18 00:34:51 2009
@@ -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}}
+}
More information about the cfe-commits
mailing list