[cfe-commits] r39443 - in /cfe/cfe/trunk: AST/Expr.cpp AST/SemaExpr.cpp AST/Type.cpp Sema/SemaExpr.cpp clang.xcodeproj/project.pbxproj include/clang/AST/Expr.h include/clang/AST/Type.h

Steve Naroff snaroff at apple.com
Wed Jul 11 09:44:28 PDT 2007


Author: snaroff
Date: Wed Jul 11 11:44:27 2007
New Revision: 39443

URL: http://llvm.org/viewvc/llvm-project?rev=39443&view=rev
Log:
Bug #:
Submitted by:
Reviewed by:
Fixed a bug in Sema::CheckAddressOfOperand(). It was (incorrectly) using
isModifiableLvalue() instead of isLvalue(). This motivated me to (finally)
cleanup methods surrounding lsLvalue/isModifiableLvalue. Cleanup involved:
- adding Expr::isLvalue().
- modified Expr::isModifiableLvalue() to use Expr::isLvalue().
- removed Type::isLvalue(), Type::isModifiableLvalue(), and
QualType::isModifiableLvalue(). They were confusing...the respective logic
is now a part of the Expr member functions...
- also added some comments and spec references, since these methods are
so central to expressions working properly.

Modified:
    cfe/cfe/trunk/AST/Expr.cpp
    cfe/cfe/trunk/AST/SemaExpr.cpp
    cfe/cfe/trunk/AST/Type.cpp
    cfe/cfe/trunk/Sema/SemaExpr.cpp
    cfe/cfe/trunk/clang.xcodeproj/project.pbxproj
    cfe/cfe/trunk/include/clang/AST/Expr.h
    cfe/cfe/trunk/include/clang/AST/Type.h

Modified: cfe/cfe/trunk/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/Expr.cpp?rev=39443&r1=39442&r2=39443&view=diff

==============================================================================
--- cfe/cfe/trunk/AST/Expr.cpp (original)
+++ cfe/cfe/trunk/AST/Expr.cpp Wed Jul 11 11:44:27 2007
@@ -118,7 +118,8 @@
   }
 }
 
-/// Nonarray expressions that can be lvalues:
+/// isLvalue - C99 6.3.2.1: an lvalue is an expression with an object type or an
+/// incomplete type other than void. Nonarray expressions that can be lvalues:
 ///  - name, where name must be a variable
 ///  - e[i]
 ///  - (e), where e must be an lvalue
@@ -127,34 +128,57 @@
 ///  - *e, the type of e cannot be a function type
 ///  - string-constant
 ///
-bool Expr::isModifiableLvalue() {
+bool Expr::isLvalue() {
+  // first, check the type (C99 6.3.2.1)
+  if (!TR->isObjectType())
+    return false;
+  if (TR->isIncompleteType() && TR->isVoidType())
+    return false;
+  
+  // now, check the expression
   switch (getStmtClass()) {
-  case StringLiteralClass:
+  case StringLiteralClass: // C99 6.5.1p4
     return true;
   case ArraySubscriptExprClass:
     return true;
-  case DeclRefExprClass:
+  case DeclRefExprClass: // C99 6.5.1p2
     const DeclRefExpr *d = cast<DeclRefExpr>(this);
-    if (const VarDecl *vd = dyn_cast<VarDecl>(d->getDecl()))
-      if (vd->getType().isModifiableLvalue())
-        return true;
-    return false;
-  case MemberExprClass:
+    return isa<VarDecl>(d->getDecl());
+  case MemberExprClass: // C99 6.5.2.3p4
     const MemberExpr *m = cast<MemberExpr>(this);
     if (m->isArrow())
       return true;
-    return m->getBase()->isModifiableLvalue(); // make sure "." is an lvalue
-  case UnaryOperatorClass:
+    return m->getBase()->isLvalue();
+  case UnaryOperatorClass: // C99 6.5.3p4
     const UnaryOperator *u = cast<UnaryOperator>(this);
-    return u->getOpcode() == UnaryOperator::Deref &&
-           u->getType().isModifiableLvalue(); // C99 6.5.3.2p4
-  case ParenExprClass:
-    return cast<ParenExpr>(this)->getSubExpr()->isModifiableLvalue();
+    return u->getOpcode() == UnaryOperator::Deref;
+  case ParenExprClass: // C99 6.5.1p5
+    return cast<ParenExpr>(this)->getSubExpr()->isLvalue();
   default: 
     return false;
   }
 }
 
+/// 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, and
+/// if it is a structure or union, does not have any member (including, 
+/// recursively, any member or element of all contained aggregates or unions)
+/// with a const-qualified type.
+bool Expr::isModifiableLvalue() {
+  if (!isLvalue())
+    return false;
+  
+  if (TR.isConstQualified())
+    return false;
+  if (TR->isArrayType())
+    return false;
+  if (TR->isIncompleteType())
+    return false;
+  if (const RecordType *r = dyn_cast<RecordType>(TR.getCanonicalType()))
+    return r->isModifiableLvalue();
+  return true;    
+}
+
 bool Expr::isConstantExpr() const {
   switch (getStmtClass()) {
   case IntegerLiteralClass:

Modified: cfe/cfe/trunk/AST/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/SemaExpr.cpp?rev=39443&r1=39442&r2=39443&view=diff

==============================================================================
--- cfe/cfe/trunk/AST/SemaExpr.cpp (original)
+++ cfe/cfe/trunk/AST/SemaExpr.cpp Wed Jul 11 11:44:27 2007
@@ -780,18 +780,10 @@
 QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) {
   Decl *dcl = getPrimaryDeclaration(op);
   
-  if (!op->isModifiableLvalue()) {
+  if (!op->isLvalue()) { // 
     if (dcl && isa<FunctionDecl>(dcl))
       ;  // C99 6.5.3.2p1: Allow function designators.
     else {
-      /* FIXME: The following produces an (incorrect) error. The 
-         Type::isModifiableLvalue() predicate is causing problems.
-      
-        const char **cpp;
-        const char c = 'A';
-
-        int main() { *cpp = &c;  // valid }
-     */
       Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof);
       return QualType();
     }

Modified: cfe/cfe/trunk/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/Type.cpp?rev=39443&r1=39442&r2=39443&view=diff

==============================================================================
--- cfe/cfe/trunk/AST/Type.cpp (original)
+++ cfe/cfe/trunk/AST/Type.cpp Wed Jul 11 11:44:27 2007
@@ -304,17 +304,6 @@
   }
 }
 
-/// isLvalue - C99 6.3.2.1: an lvalue is an expression with an object type or
-/// an incomplete type other than void.
-bool Type::isLvalue() const {
-  if (isObjectType())
-    return true;
-  else if (isIncompleteType())
-    return isVoidType() ? false : true;
-  else 
-    return false;    
-}
-
 bool Type::isPromotableIntegerType() const {
   if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) {
     switch (BT->getKind()) {
@@ -332,32 +321,6 @@
   return false;
 }
 
-/// 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, and
-/// if it is a structure or union, does not have any member (including, 
-/// recursively, any member or element of all contained aggregates or unions)
-/// with a const-qualified type.
-
-bool QualType::isModifiableLvalue() const {
-  if (isConstQualified())
-    return false;
-  else
-    return getTypePtr()->isModifiableLvalue();
-}
-
-bool Type::isModifiableLvalue() const {
-  if (!isLvalue())
-    return false;
-    
-  if (isArrayType())
-    return false;
-  if (isIncompleteType())
-    return false;
-  if (const RecordType *r = dyn_cast<RecordType>(this))
-    return r->isModifiableLvalue();
-  return true;    
-}
-
 const char *BuiltinType::getName() const {
   switch (getKind()) {
   default: assert(0 && "Unknown builtin type!");

Modified: cfe/cfe/trunk/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/SemaExpr.cpp?rev=39443&r1=39442&r2=39443&view=diff

==============================================================================
--- cfe/cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaExpr.cpp Wed Jul 11 11:44:27 2007
@@ -780,18 +780,10 @@
 QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) {
   Decl *dcl = getPrimaryDeclaration(op);
   
-  if (!op->isModifiableLvalue()) {
+  if (!op->isLvalue()) { // 
     if (dcl && isa<FunctionDecl>(dcl))
       ;  // C99 6.5.3.2p1: Allow function designators.
     else {
-      /* FIXME: The following produces an (incorrect) error. The 
-         Type::isModifiableLvalue() predicate is causing problems.
-      
-        const char **cpp;
-        const char c = 'A';
-
-        int main() { *cpp = &c;  // valid }
-     */
       Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof);
       return QualType();
     }

Modified: cfe/cfe/trunk/clang.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/clang.xcodeproj/project.pbxproj?rev=39443&r1=39442&r2=39443&view=diff

==============================================================================
--- cfe/cfe/trunk/clang.xcodeproj/project.pbxproj (original)
+++ cfe/cfe/trunk/clang.xcodeproj/project.pbxproj Wed Jul 11 11:44:27 2007
@@ -171,7 +171,7 @@
 		1A30A9E80B93A4C800201A91 /* ExprCXX.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ExprCXX.h; path = clang/AST/ExprCXX.h; sourceTree = "<group>"; };
 		1A869A6E0BA2164C008DA07A /* LiteralSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LiteralSupport.h; sourceTree = "<group>"; };
 		1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LiteralSupport.cpp; sourceTree = "<group>"; };
-		8DD76F6C0486A84900D96B5E /* clang */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = clang; sourceTree = BUILT_PRODUCTS_DIR; };
+		8DD76F6C0486A84900D96B5E /* clang */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "compiled.mach-o.executable"; path = clang; sourceTree = BUILT_PRODUCTS_DIR; };
 		DE01DA480B12ADA300AC22CE /* PPCallbacks.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PPCallbacks.h; sourceTree = "<group>"; };
 		DE06B73D0A8307640050E87E /* LangOptions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = LangOptions.h; sourceTree = "<group>"; };
 		DE06BECA0A854E4B0050E87E /* Scope.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Scope.h; path = clang/Parse/Scope.h; sourceTree = "<group>"; };

Modified: cfe/cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/AST/Expr.h?rev=39443&r1=39442&r2=39443&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/cfe/trunk/include/clang/AST/Expr.h Wed Jul 11 11:44:27 2007
@@ -35,15 +35,23 @@
 public:  
   QualType getType() const { return TR; }
   
-  /// isModifiableLvalue - return true if the expression is one of the following:
+  /// isLvalue - C99 6.3.2.1: an lvalue is an expression with an object type or
+  /// incomplete type other than void. Nonarray expressions that can be lvalues:
   ///  - name, where name must be a variable
   ///  - e[i]
   ///  - (e), where e must be an lvalue
   ///  - e.name, where e must be an lvalue
   ///  - e->name
-  ///  - *e, where e must be an lvalue (pointer-to-function isn't an lvalue)
+  ///  - *e, the type of e cannot be a function type
   ///  - string-constant
   ///
+  bool isLvalue();
+  
+  /// 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,
+  /// and if it is a structure or union, does not have any member (including, 
+  /// recursively, any member or element of all contained aggregates or unions)
+  /// with a const-qualified type.
   bool isModifiableLvalue();
   
   bool isNullPointerConstant() const;

Modified: cfe/cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/AST/Type.h?rev=39443&r1=39442&r2=39443&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/cfe/trunk/include/clang/AST/Type.h Wed Jul 11 11:44:27 2007
@@ -112,13 +112,6 @@
   bool operator!=(const QualType &RHS) const {
     return ThePtr != RHS.ThePtr;
   }
-  /// isModifiableLvalue - C99 6.3.2.1p1: returns true if the type is an lvalue
-  /// that does not have array type, does not have an incomplete type, does
-  /// not have a const-qualified type, and if it is a struct/union, does not 
-  /// have any member (including, recursively, any member or element of all
-  /// contained aggregates or unions) with a const-qualified type.
-  bool isModifiableLvalue() const;
-    
   void getAsString(std::string &S) const;
   void dump(const char *s = 0) const;
 
@@ -227,8 +220,6 @@
   bool isScalarType() const;       // C99 6.2.5p21 (arithmetic + pointers)
   bool isAggregateType() const;    // C99 6.2.5p21 (arrays, structures)
   
-  bool isLvalue() const;         // C99 6.3.2.1
-  
   /// More type predicates useful for type checking/promotion
   bool isPromotableIntegerType() const; // C99 6.3.1.1p2
   bool isSignedIntegerType() const;     // C99 6.2.5p4
@@ -242,11 +233,7 @@
   static bool pointerTypesAreCompatible(QualType, QualType);  // C99 6.7.5.1p2
   static bool functionTypesAreCompatible(QualType, QualType); // C99 6.7.5.3p15
   static bool arrayTypesAreCompatible(QualType, QualType); // C99 6.7.5.2p6
-private:
-  // this forces clients to use isModifiableLvalue on QualType, the class that 
-  // knows if the type is const. This predicate is a helper to QualType. 
-  bool isModifiableLvalue() const; // C99 6.3.2.1p1
-  
+private:  
   QualType getCanonicalTypeInternal() const { return CanonicalType; }
   friend class QualType;
 public:





More information about the cfe-commits mailing list