Author: dgregor Date: Thu Jan 22 18:36:41 2009 New Revision: 62823 URL: http://llvm.org/viewvc/llvm-project?rev=62823&view=rev Log: Support arithmetic on pointer-to-function types as a GNU extension. Addresses clang PR/3371.
Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def cfe/trunk/lib/Sema/SemaExpr.cpp cfe/trunk/test/Sema/pointer-addition.c Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=62823&r1=62822&r2=62823&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original) +++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Thu Jan 22 18:36:41 2009 @@ -345,7 +345,9 @@ "use of GNU old-style field designator extension") DIAG(ext_gnu_case_range, EXTENSION, "use of GNU case range extension") - +DIAG(ext_gnu_ptr_func_arith, EXTENSION, + "arithmetic on pointer to function type %0 is a GNU extension") + // Generic errors. DIAG(err_parse_error, ERROR, "parse error") @@ -1262,6 +1264,8 @@ "arithmetic on pointer to incomplete type %0") DIAG(err_typecheck_pointer_arith_function_type, ERROR, "arithmetic on pointer to function type %0") +DIAG(err_typecheck_pointer_arith_void_type, ERROR, + "arithmetic on pointer to void type") DIAG(err_typecheck_decl_incomplete_type, ERROR, "variable has incomplete type %0") // FIXME: Use %select Modified: cfe/trunk/lib/Sema/SemaExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=62823&r1=62822&r2=62823&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) +++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Jan 22 18:36:41 2009 @@ -2656,12 +2656,25 @@ // Check for arithmetic on pointers to incomplete types if (!PTy->getPointeeType()->isObjectType()) { if (PTy->getPointeeType()->isVoidType()) { + if (getLangOptions().CPlusPlus) { + Diag(Loc, diag::err_typecheck_pointer_arith_void_type) + << lex->getSourceRange() << rex->getSourceRange(); + return QualType(); + } + + // GNU extension: arithmetic on pointer to void Diag(Loc, diag::ext_gnu_void_ptr) << lex->getSourceRange() << rex->getSourceRange(); } else if (PTy->getPointeeType()->isFunctionType()) { - Diag(Loc, diag::err_typecheck_pointer_arith_function_type) + if (getLangOptions().CPlusPlus) { + Diag(Loc, diag::err_typecheck_pointer_arith_function_type) + << lex->getType() << lex->getSourceRange(); + return QualType(); + } + + // GNU extension: arithmetic on pointer to function + Diag(Loc, diag::ext_gnu_ptr_func_arith) << lex->getType() << lex->getSourceRange(); - return QualType(); } else { DiagnoseIncompleteType(Loc, PTy->getPointeeType(), diag::err_typecheck_arithmetic_incomplete_type, @@ -2701,6 +2714,16 @@ if (lpointee->isVoidType()) { Diag(Loc, diag::ext_gnu_void_ptr) << lex->getSourceRange() << rex->getSourceRange(); + } else if (lpointee->isFunctionType()) { + if (getLangOptions().CPlusPlus) { + Diag(Loc, diag::err_typecheck_pointer_arith_function_type) + << lex->getType() << lex->getSourceRange(); + return QualType(); + } + + // GNU extension: arithmetic on pointer to function + Diag(Loc, diag::ext_gnu_ptr_func_arith) + << lex->getType() << lex->getSourceRange(); } else { Diag(Loc, diag::err_typecheck_sub_ptr_object) << lex->getType() << lex->getSourceRange(); @@ -3174,10 +3197,22 @@ if (PT->getPointeeType()->isObjectType()) { // Pointer to object is ok! } else if (PT->getPointeeType()->isVoidType()) { - // Pointer to void is extension. + if (getLangOptions().CPlusPlus) { + Diag(OpLoc, diag::err_typecheck_pointer_arith_void_type) + << Op->getSourceRange(); + return QualType(); + } + + // Pointer to void is a GNU extension in C. Diag(OpLoc, diag::ext_gnu_void_ptr) << Op->getSourceRange(); } else if (PT->getPointeeType()->isFunctionType()) { - Diag(OpLoc, diag::err_typecheck_pointer_arith_function_type) + if (getLangOptions().CPlusPlus) { + Diag(OpLoc, diag::err_typecheck_pointer_arith_function_type) + << Op->getType() << Op->getSourceRange(); + return QualType(); + } + + Diag(OpLoc, diag::ext_gnu_ptr_func_arith) << ResType << Op->getSourceRange(); return QualType(); } else { Modified: cfe/trunk/test/Sema/pointer-addition.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/pointer-addition.c?rev=62823&r1=62822&r2=62823&view=diff ============================================================================== --- cfe/trunk/test/Sema/pointer-addition.c (original) +++ cfe/trunk/test/Sema/pointer-addition.c Thu Jan 22 18:36:41 2009 @@ -2,13 +2,18 @@ typedef struct S S; // expected-note{{forward declaration of 'struct S'}} void a(S* b, void* c) { + void (*fp)(int) = 0; b++; // expected-error {{arithmetic on pointer to incomplete type}} b += 1; // expected-error {{arithmetic on pointer to incomplete type}} c++; // expected-warning {{use of GNU void* extension}} c += 1; // expected-warning {{use of GNU void* extension}} + c--; // expected-warning {{use of GNU void* extension}} + c -= 1; // expected-warning {{use of GNU void* extension}} b = 1+b; // expected-error {{arithmetic on pointer to incomplete type}} /* The next couple tests are only pedantic warnings in gcc */ void (*d)(S*,void*) = a; - d += 1; // expected-error {{arithmetic on pointer to function type}}} - d++; // expected-error {{arithmetic on pointer to function type}}} + d += 1; // expected-warning {{arithmetic on pointer to function type 'void (*)(S *, void *)' is a GNU extension}} + d++; // expected-warning {{arithmetic on pointer to function type 'void (*)(S *, void *)' is a GNU extension}}} + d--; // expected-warning {{arithmetic on pointer to function type 'void (*)(S *, void *)' is a GNU extension}} + d -= 1; // expected-warning {{arithmetic on pointer to function type 'void (*)(S *, void *)' is a GNU extension}} } _______________________________________________ cfe-commits mailing list cfe-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits