diff options
| author | Eli Friedman <eli.friedman@gmail.com> | 2009-05-03 22:36:05 +0000 | 
|---|---|---|
| committer | Eli Friedman <eli.friedman@gmail.com> | 2009-05-03 22:36:05 +0000 | 
| commit | b8c4fd8cfd27dbc63e1706729be4b330bf946a0c (patch) | |
| tree | 49b37e6478c4351aec75ff84f6f8696af839cde3 /clang | |
| parent | ba49fef34a7150c74f244e6fe134830d44587998 (diff) | |
| download | bcm5719-llvm-b8c4fd8cfd27dbc63e1706729be4b330bf946a0c.tar.gz bcm5719-llvm-b8c4fd8cfd27dbc63e1706729be4b330bf946a0c.zip | |
PR2524: downgrade taking address of expression of type 'void' to an 
extension warning.
llvm-svn: 70805
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/include/clang/AST/Expr.h | 3 | ||||
| -rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
| -rw-r--r-- | clang/lib/AST/Expr.cpp | 16 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 7 | ||||
| -rw-r--r-- | clang/test/Sema/deref.c | 7 | ||||
| -rw-r--r-- | clang/test/Sema/varargs.c | 2 | 
6 files changed, 27 insertions, 10 deletions
| diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 38d2124e643..441aae2c730 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -147,6 +147,9 @@ public:      LV_MemberFunction    };    isLvalueResult isLvalue(ASTContext &Ctx) const; + +  // Same as above, but excluding checks for non-object and void types in C +  isLvalueResult isLvalueInternal(ASTContext &Ctx) const;    /// isModifiableLvalue - C99 6.3.2.1: an lvalue that does not have array type,    /// does not have an incomplete type, does not have a const-qualified type, diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 0e6ce3b0720..1ea237eef51 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1021,6 +1021,8 @@ def err_typecheck_sclass_func : Error<"illegal storage class on function">;  def err_static_block_func : Error<    "function declared in block scope cannot have 'static' storage class">;  def err_typecheck_address_of : Error<"address of %0 requested">; +def ext_typecheck_addrof_void : Extension< +  "ISO C forbids taking the address of an expression of type 'void'">;  def err_typecheck_invalid_lvalue_addrof : Error<    "address expression must be an lvalue or a function designator">;  def err_typecheck_unary_expr : Error< diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 19d67bb7f8a..13d2a1be3f9 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -603,18 +603,26 @@ static bool DeclCanBeLvalue(const NamedDecl *Decl, ASTContext &Ctx) {  ///  - reference type [C++ [expr]]  ///  Expr::isLvalueResult Expr::isLvalue(ASTContext &Ctx) const { +  assert(!TR->isReferenceType() && "Expressions can't have reference type."); + +  isLvalueResult Res = isLvalueInternal(Ctx); +  if (Res != LV_Valid || Ctx.getLangOptions().CPlusPlus) +    return Res; +    // first, check the type (C99 6.3.2.1). Expressions with function    // type in C are not lvalues, but they can be lvalues in C++. -  if (!Ctx.getLangOptions().CPlusPlus && TR->isFunctionType()) +  if (TR->isFunctionType())      return LV_NotObjectType;    // Allow qualified void which is an incomplete type other than void (yuck).    if (TR->isVoidType() && !Ctx.getCanonicalType(TR).getCVRQualifiers())      return LV_IncompleteVoidType; -  assert(!TR->isReferenceType() && "Expressions can't have reference type."); +  return LV_Valid; +} -  // the type looks fine, now check the expression +// Check whether the expression can be sanely treated like an l-value +Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const {    switch (getStmtClass()) {    case StringLiteralClass:  // C99 6.5.1p4    case ObjCEncodeExprClass: // @encode behaves like its string in every way. @@ -754,8 +762,6 @@ Expr::isLvalueResult Expr::isLvalue(ASTContext &Ctx) const {      return LV_Valid;    case PredefinedExprClass:      return LV_Valid; -  case VAArgExprClass: -    return LV_NotObjectType;    case CXXDefaultArgExprClass:      return cast<CXXDefaultArgExpr>(this)->getExpr()->isLvalue(Ctx);    case CXXConditionDeclExprClass: diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 6ce98cd28f7..36ec9c65c13 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -4245,7 +4245,12 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) {    if (lval != Expr::LV_Valid) { // C99 6.5.3.2p1      // The operand must be either an l-value or a function designator -    if (!op->getType()->isFunctionType()) { +    if (op->getType()->isFunctionType()) { +      // Function designator is valid +    } else if (lval == Expr::LV_IncompleteVoidType) { +      Diag(OpLoc, diag::ext_typecheck_addrof_void) +        << op->getSourceRange(); +    } else {        // FIXME: emit more specific diag...        Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof)          << op->getSourceRange(); diff --git a/clang/test/Sema/deref.c b/clang/test/Sema/deref.c index fad56430a07..965940e26d5 100644 --- a/clang/test/Sema/deref.c +++ b/clang/test/Sema/deref.c @@ -1,4 +1,5 @@ -// RUN: clang-cc -fsyntax-only -verify -std=c90 %s +/* RUN: clang-cc -fsyntax-only -verify -std=c90 -pedantic %s + */  void  foo (void)  { @@ -17,7 +18,7 @@ void foo2 (void)  void foo3 (void)  {   void* x = 0; - void* y = &*x; // expected-error{{address expression must be an lvalue or a function designator}} + void* y = &*x; /* expected-warning{{address of an expression of type 'void'}} */  }  extern const void cv1; @@ -30,7 +31,7 @@ const void *foo4 (void)  extern void cv2;  void *foo5 (void)  { -  return &cv2; // expected-error{{address expression must be an lvalue or a function designator}} +  return &cv2; /* expected-warning{{address of an expression of type 'void'}} */  }  typedef const void CVT; diff --git a/clang/test/Sema/varargs.c b/clang/test/Sema/varargs.c index d5b4aac6f7d..8d2f0b1fa83 100644 --- a/clang/test/Sema/varargs.c +++ b/clang/test/Sema/varargs.c @@ -56,7 +56,7 @@ void f7(int a, ...) {    __builtin_va_list ap;    __builtin_va_start(ap, a);    // FIXME: This error message is sub-par. -  __builtin_va_arg(ap, int) = 1; // expected-error {{non-object type 'int' is not assignable}} +  __builtin_va_arg(ap, int) = 1; // expected-error {{expression is not assignable}}    int *x = &__builtin_va_arg(ap, int); // expected-error {{address expression must be an lvalue or a function designator}}    __builtin_va_end(ap);  } | 

