diff options
| -rw-r--r-- | clang/include/clang/Basic/DiagnosticKinds.def | 6 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 43 | ||||
| -rw-r--r-- | clang/test/Sema/pointer-addition.c | 9 | 
3 files changed, 51 insertions, 7 deletions
| diff --git a/clang/include/clang/Basic/DiagnosticKinds.def b/clang/include/clang/Basic/DiagnosticKinds.def index 259265c2bfc..1858f2583be 100644 --- a/clang/include/clang/Basic/DiagnosticKinds.def +++ b/clang/include/clang/Basic/DiagnosticKinds.def @@ -345,7 +345,9 @@ DIAG(ext_gnu_old_style_field_designator, EXTENSION,       "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 @@ DIAG(err_typecheck_arithmetic_incomplete_type, ERROR,       "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 diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 8cf153e673d..ab5bd6bd119 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2656,12 +2656,25 @@ inline QualType Sema::CheckAdditionOperands( // C99 6.5.6        // 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 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex,        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 @@ QualType Sema::CheckIncrementDecrementOperand(Expr *Op, SourceLocation OpLoc,      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 { diff --git a/clang/test/Sema/pointer-addition.c b/clang/test/Sema/pointer-addition.c index 95f364fc676..81a1dc06c1f 100644 --- a/clang/test/Sema/pointer-addition.c +++ b/clang/test/Sema/pointer-addition.c @@ -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}}  } | 

