summaryrefslogtreecommitdiffstats
path: root/clang/AST/SemaExpr.cpp
diff options
context:
space:
mode:
authorSteve Naroff <snaroff@apple.com>2007-04-19 23:00:49 +0000
committerSteve Naroff <snaroff@apple.com>2007-04-19 23:00:49 +0000
commit4750051ebbb3a76c92c875f8cd58e5a317c09a23 (patch)
tree64a6b1969d162ebf5905462f022ef0cee1dd459f /clang/AST/SemaExpr.cpp
parent89399da91a389040510201e76b57f1b0f196bda3 (diff)
downloadbcm5719-llvm-4750051ebbb3a76c92c875f8cd58e5a317c09a23.tar.gz
bcm5719-llvm-4750051ebbb3a76c92c875f8cd58e5a317c09a23.zip
Bug #:
Submitted by: Reviewed by: Continue working on type checking for unary operators. Added: - Two 3 private functions to Sema: CheckAddressOfOperand(), CheckIndirectionOperand(), and getDecl(). - Added Expr::isLvalue() - it was needed for CheckAddressOfOperand(). It will also be needed for ++/-- and the assignment operators. - Added a couple diagnostics for invalid lvalues (for & of). llvm-svn: 39408
Diffstat (limited to 'clang/AST/SemaExpr.cpp')
-rw-r--r--clang/AST/SemaExpr.cpp65
1 files changed, 65 insertions, 0 deletions
diff --git a/clang/AST/SemaExpr.cpp b/clang/AST/SemaExpr.cpp
index c8287af3911..69438fea514 100644
--- a/clang/AST/SemaExpr.cpp
+++ b/clang/AST/SemaExpr.cpp
@@ -176,6 +176,10 @@ Action::ExprResult Sema::ParseUnaryOp(SourceLocation OpLoc, tok::TokenKind Op,
}
if (Opc == UnaryOperator::PreInc || Opc == UnaryOperator::PreDec)
return CheckIncrementDecrementOperand((Expr *)Input, OpLoc, Opc);
+ else if (Opc == UnaryOperator::AddrOf)
+ return CheckAddressOfOperand((Expr *)Input, OpLoc, Opc);
+ else if (Opc == UnaryOperator::Deref)
+ return CheckIndirectionOperand((Expr *)Input, OpLoc, Opc);
// when all the check functions are written, this will go away...
return new UnaryOperator((Expr*)Input, Opc, QualType());
@@ -451,3 +455,64 @@ Sema::CheckIncrementDecrementOperand(Expr *op, SourceLocation OpLoc,
return new UnaryOperator(op, (UnaryOperator::Opcode)OpCode, qType);
}
+/// getDecl - This is currently a helper function for CheckAddressOfOperand().
+/// This routine allows us to typecheck complex/recursive expressions
+/// where the declaration is needed for type checking. Here are some
+/// examples: &s.xx, &s.zz[1].yy, &(1+2), &(XX), &"123"[2].
+Decl *Sema::getDecl(Expr *e) {
+ switch (e->getStmtClass()) {
+ case Stmt::DeclRefExprClass:
+ return cast<DeclRefExpr>(e)->getDecl();
+ case Stmt::MemberExprClass:
+ return getDecl(cast<MemberExpr>(e)->getBase());
+ case Stmt::ArraySubscriptExprClass:
+ return getDecl(cast<ArraySubscriptExpr>(e)->getBase());
+ case Stmt::CallExprClass:
+ return getDecl(cast<CallExpr>(e)->getCallee());
+ case Stmt::UnaryOperatorClass:
+ return getDecl(cast<UnaryOperator>(e)->getSubExpr());
+ case Stmt::ParenExprClass:
+ return getDecl(cast<ParenExpr>(e)->getSubExpr());
+ default:
+ return 0;
+ }
+}
+
+/// CheckAddressOfOperand - The operand of & must be either a function
+/// designator or an lvalue designating an object. If it is an lvalue, the
+/// object cannot be declared with storage class register or be a bit field.
+/// Note: The usual conversions are *not* applied to the operand of the &
+/// operator, and its result is never an lvalue.
+Action::ExprResult
+Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc, unsigned OpCode) {
+ Decl *dcl = getDecl(op);
+
+ if (!op->isLvalue()) {
+ if (dcl && isa<FunctionDecl>(dcl))
+ ; // C99 6.5.3.2p1: Allow function designators.
+ else
+ return Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof);
+ } else if (dcl) {
+ // We have an lvalue with a decl. Make sure the decl is not declared
+ // with the register storage-class specifier.
+ if (const VarDecl *vd = dyn_cast<VarDecl>(dcl)) {
+ if (vd->getStorageClass() == VarDecl::Register)
+ return Diag(OpLoc, diag::err_typecheck_address_of_register);
+ }
+ // FIXME: add check for bitfields!
+ }
+ // If the operand has type "type", the result has type "pointer to type".
+ return new UnaryOperator(op, (UnaryOperator::Opcode)OpCode,
+ Context.getPointerType(op->getType()));
+}
+
+Action::ExprResult
+Sema::CheckIndirectionOperand(Expr *op, SourceLocation OpLoc, unsigned OpCode) {
+ QualType qType = op->getType();
+
+ assert(!qType.isNull() && "no type for * expression");
+
+ QualType canonType = qType.getCanonicalType();
+
+ return new UnaryOperator(op, (UnaryOperator::Opcode)OpCode, QualType());
+}
OpenPOWER on IntegriCloud