[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