diff options
author | Chris Lattner <sabre@nondot.org> | 2008-01-03 22:56:36 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2008-01-03 22:56:36 +0000 |
commit | bfe639e4d39b1afa05d66aaea0378d6c10df4ffc (patch) | |
tree | 7a7cb2434f1ba663661efc390023627637e263c3 | |
parent | 58ca5f5d6aad90a2647a2b8b8baddd714cf6da65 (diff) |
give better diagnostics for converting between function pointer and void*.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@45556 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | Sema/Sema.h | 1 | ||||
-rw-r--r-- | Sema/SemaDecl.cpp | 5 | ||||
-rw-r--r-- | Sema/SemaExpr.cpp | 45 | ||||
-rw-r--r-- | Sema/SemaStmt.cpp | 5 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticKinds.def | 11 | ||||
-rw-r--r-- | test/Sema/function-ptr.c | 11 |
6 files changed, 69 insertions, 9 deletions
diff --git a/Sema/Sema.h b/Sema/Sema.h index 7faac13458..33fd345d00 100644 --- a/Sema/Sema.h +++ b/Sema/Sema.h @@ -612,6 +612,7 @@ private: Incompatible, PointerFromInt, IntFromPointer, + FunctionVoidPointer, IncompatiblePointer, CompatiblePointerDiscardsQualifiers }; diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp index 5a588397d9..1165e526d8 100644 --- a/Sema/SemaDecl.cpp +++ b/Sema/SemaDecl.cpp @@ -394,6 +394,11 @@ bool Sema::CheckSingleInitializer(Expr *&Init, bool isStatic, DeclType.getAsString(), rhsType.getAsString(), Init->getSourceRange()); break; + case FunctionVoidPointer: + Diag(Init->getLocStart(), diag::ext_typecheck_assign_pointer_void_func, + DeclType.getAsString(), rhsType.getAsString(), + Init->getSourceRange()); + break; case IncompatiblePointer: Diag(Init->getLocStart(), diag::ext_typecheck_assign_incompatible_pointer, DeclType.getAsString(), rhsType.getAsString(), diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp index 1ec60d9934..68c301afd8 100644 --- a/Sema/SemaExpr.cpp +++ b/Sema/SemaExpr.cpp @@ -644,6 +644,11 @@ ActOnCallExpr(ExprTy *fn, SourceLocation LParenLoc, LHSType.getAsString(), RHSType.getAsString(), Fn->getSourceRange(), Arg->getSourceRange()); break; + case FunctionVoidPointer: + Diag(Loc, diag::ext_typecheck_passing_pointer_void_func, + LHSType.getAsString(), RHSType.getAsString(), + Fn->getSourceRange(), Arg->getSourceRange()); + break; case IncompatiblePointer: Diag(Loc, diag::ext_typecheck_passing_incompatible_pointer, RHSType.getAsString(), LHSType.getAsString(), @@ -1075,17 +1080,29 @@ Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) { // C99 6.5.16.1p1 (constraint 4): If one operand is a pointer to an object or // incomplete type and the other is a pointer to a qualified or unqualified // version of void... - if (lhptee.getUnqualifiedType()->isVoidType() && - (rhptee->isObjectType() || rhptee->isIncompleteType())) - ; - else if (rhptee.getUnqualifiedType()->isVoidType() && - (lhptee->isObjectType() || lhptee->isIncompleteType())) - ; + if (lhptee->isVoidType()) { + if (rhptee->isObjectType() || rhptee->isIncompleteType()) + return r; + + // As an extension, we allow cast to/from void* to function pointer. + if (rhptee->isFunctionType()) + return FunctionVoidPointer; + } + + if (rhptee->isVoidType()) { + if (lhptee->isObjectType() || lhptee->isIncompleteType()) + return r; + + // As an extension, we allow cast to/from void* to function pointer. + if (lhptee->isFunctionType()) + return FunctionVoidPointer; + } + // C99 6.5.16.1p1 (constraint 3): both operands are pointers to qualified or // unqualified versions of compatible types, ... - else if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(), - rhptee.getUnqualifiedType())) - r = IncompatiblePointer; // this "trumps" PointerAssignDiscardsQualifiers + if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(), + rhptee.getUnqualifiedType())) + return IncompatiblePointer; // this "trumps" PointerAssignDiscardsQualifiers return r; } @@ -1543,6 +1560,11 @@ inline QualType Sema::CheckAssignmentOperands( // C99 6.5.16.1 lhsType.getAsString(), rhsType.getAsString(), lex->getSourceRange(), rex->getSourceRange()); break; + case FunctionVoidPointer: + Diag(loc, diag::ext_typecheck_assign_pointer_void_func, + lhsType.getAsString(), rhsType.getAsString(), + lex->getSourceRange(), rex->getSourceRange()); + break; case IncompatiblePointer: Diag(loc, diag::ext_typecheck_assign_incompatible_pointer, lhsType.getAsString(), rhsType.getAsString(), @@ -2226,6 +2248,11 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, rhsType.getAsString(), lhsType.getAsString(), argExpr->getSourceRange()); break; + case FunctionVoidPointer: + Diag(l, diag::ext_typecheck_sending_pointer_void_func, + rhsType.getAsString(), lhsType.getAsString(), + argExpr->getSourceRange()); + break; case CompatiblePointerDiscardsQualifiers: Diag(l, diag::ext_typecheck_passing_discards_qualifiers, rhsType.getAsString(), lhsType.getAsString(), diff --git a/Sema/SemaStmt.cpp b/Sema/SemaStmt.cpp index cbb01bdb3c..2c2dc5e3f0 100644 --- a/Sema/SemaStmt.cpp +++ b/Sema/SemaStmt.cpp @@ -663,6 +663,11 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, ExprTy *rex) { lhsType.getAsString(), rhsType.getAsString(), RetValExp->getSourceRange()); break; + case FunctionVoidPointer: + Diag(ReturnLoc, diag::ext_typecheck_return_pointer_void_func, + lhsType.getAsString(), rhsType.getAsString(), + RetValExp->getSourceRange()); + break; case IncompatiblePointer: Diag(ReturnLoc, diag::ext_typecheck_return_incompatible_pointer, lhsType.getAsString(), rhsType.getAsString(), diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index 591e3059a8..0f31c922cf 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -767,6 +767,8 @@ DIAG(ext_typecheck_assign_incompatible_pointer, WARNING, "incompatible pointer types assigning '%1' to '%0'") DIAG(ext_typecheck_assign_discards_qualifiers, WARNING, "assigning '%1' to '%0' discards qualifiers") +DIAG(ext_typecheck_assign_pointer_void_func, EXTENSION, + "assigning '%1' to '%0' converts between void* and function pointer") DIAG(err_typecheck_array_not_modifiable_lvalue, ERROR, "array type '%0' is not assignable") DIAG(err_typecheck_non_object_not_modifiable_lvalue, ERROR, @@ -791,6 +793,9 @@ DIAG(ext_typecheck_passing_incompatible_pointer, WARNING, "incompatible pointer types passing '%0' to function expecting '%1'") DIAG(ext_typecheck_passing_pointer_int, WARNING, "incompatible types passing '%1' to function expecting '%0'") +DIAG(ext_typecheck_passing_pointer_void_func, EXTENSION, + "passing '%1' to function expecting '%0' converts between void*" + " and function pointer") DIAG(ext_typecheck_passing_discards_qualifiers, WARNING, "passing '%0' to '%1' discards qualifiers") DIAG(err_typecheck_sending_incompatible, ERROR, @@ -799,6 +804,9 @@ DIAG(ext_typecheck_sending_incompatible_pointer, WARNING, "incompatible pointer types passing '%0' to method expecting '%1'") DIAG(ext_typecheck_sending_pointer_int, WARNING, "incompatible types passing '%1' to method expecting '%0'") +DIAG(ext_typecheck_sending_pointer_void_func, EXTENSION, + "sending '%1' to method expecting '%0' converts between void*" + " and function pointer") DIAG(err_typecheck_cond_expect_scalar, ERROR, "used type '%0' where arithmetic or pointer type is required") DIAG(err_typecheck_expect_scalar_operand, ERROR, @@ -909,6 +917,9 @@ DIAG(err_typecheck_return_incompatible, ERROR, "incompatible type returning '%1', expected '%0'") DIAG(ext_typecheck_return_pointer_int, EXTENSION, "incompatible type returning '%1', expected '%0'") +DIAG(ext_typecheck_return_pointer_void_func, EXTENSION, + "returning '%1' to from function expecting '%0' converts between void*" + " and function pointer") DIAG(ext_typecheck_return_incompatible_pointer, EXTENSION, "incompatible pointer type returning '%1', expected '%0'") DIAG(ext_typecheck_return_discards_qualifiers, EXTENSION, diff --git a/test/Sema/function-ptr.c b/test/Sema/function-ptr.c new file mode 100644 index 0000000000..83e4d74b6a --- /dev/null +++ b/test/Sema/function-ptr.c @@ -0,0 +1,11 @@ +// RUN: clang %s -verify -pedantic +typedef int unary_int_func(int arg); +unary_int_func *func; + +unary_int_func *set_func(void *p) { + func = p; // expected-warning {{converts between void* and function pointer}} + p = func; // expected-warning {{converts between void* and function pointer}} + + return p; // expected-warning {{converts between void* and function pointer}} +} + |