2006-11-10 05:03:26 +00:00
|
|
|
//===--- SemaExpr.cpp - Semantic Analysis for Expressions -----------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file was developed by Chris Lattner and is distributed under
|
|
|
|
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements semantic analysis for expressions.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "Sema.h"
|
2006-11-10 06:20:45 +00:00
|
|
|
#include "clang/AST/ASTContext.h"
|
2006-11-20 04:58:19 +00:00
|
|
|
#include "clang/AST/Decl.h"
|
2007-10-02 20:01:56 +00:00
|
|
|
#include "clang/AST/DeclObjC.h"
|
2006-11-10 05:03:26 +00:00
|
|
|
#include "clang/AST/Expr.h"
|
2007-09-18 23:55:05 +00:00
|
|
|
#include "clang/Parse/DeclSpec.h"
|
2006-11-10 05:03:26 +00:00
|
|
|
#include "clang/Lex/Preprocessor.h"
|
2007-03-09 23:16:33 +00:00
|
|
|
#include "clang/Lex/LiteralSupport.h"
|
2007-03-13 20:29:44 +00:00
|
|
|
#include "clang/Basic/SourceManager.h"
|
2006-11-10 05:03:26 +00:00
|
|
|
#include "clang/Basic/Diagnostic.h"
|
2006-11-20 06:49:47 +00:00
|
|
|
#include "clang/Basic/LangOptions.h"
|
2006-11-10 05:03:26 +00:00
|
|
|
#include "clang/Basic/TargetInfo.h"
|
|
|
|
#include "llvm/ADT/SmallString.h"
|
2007-08-10 20:18:51 +00:00
|
|
|
#include "llvm/ADT/StringExtras.h"
|
2006-11-10 05:03:26 +00:00
|
|
|
using namespace clang;
|
|
|
|
|
2007-09-16 03:34:24 +00:00
|
|
|
/// ActOnStringLiteral - The specified tokens were lexed as pasted string
|
2006-11-10 05:03:26 +00:00
|
|
|
/// fragments (e.g. "foo" "bar" L"baz"). The result string has to handle string
|
|
|
|
/// concatenation ([C99 5.1.1.2, translation phase #6]), so it may come from
|
|
|
|
/// multiple tokens. However, the common case is that StringToks points to one
|
|
|
|
/// string.
|
|
|
|
///
|
|
|
|
Action::ExprResult
|
2007-09-16 03:34:24 +00:00
|
|
|
Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) {
|
2006-11-10 05:03:26 +00:00
|
|
|
assert(NumStringToks && "Must have at least one string!");
|
|
|
|
|
2007-03-13 22:37:02 +00:00
|
|
|
StringLiteralParser Literal(StringToks, NumStringToks, PP, Context.Target);
|
|
|
|
if (Literal.hadError)
|
|
|
|
return ExprResult(true);
|
2006-11-10 05:03:26 +00:00
|
|
|
|
2007-06-15 23:05:46 +00:00
|
|
|
llvm::SmallVector<SourceLocation, 4> StringTokLocs;
|
2006-11-10 05:03:26 +00:00
|
|
|
for (unsigned i = 0; i != NumStringToks; ++i)
|
|
|
|
StringTokLocs.push_back(StringToks[i].getLocation());
|
2007-03-23 22:27:02 +00:00
|
|
|
|
|
|
|
// FIXME: handle wchar_t
|
2007-10-15 02:50:23 +00:00
|
|
|
QualType t;
|
|
|
|
|
|
|
|
if (Literal.Pascal)
|
|
|
|
t = Context.getPointerType(Context.UnsignedCharTy);
|
|
|
|
else
|
|
|
|
t = Context.getPointerType(Context.CharTy);
|
|
|
|
|
|
|
|
if (Literal.Pascal && Literal.GetStringLength() > 256)
|
|
|
|
return Diag(StringToks[0].getLocation(), diag::err_pascal_string_too_long,
|
|
|
|
SourceRange(StringToks[0].getLocation(),
|
|
|
|
StringToks[NumStringToks-1].getLocation()));
|
2007-03-23 22:27:02 +00:00
|
|
|
|
2006-11-10 05:03:26 +00:00
|
|
|
// Pass &StringTokLocs[0], StringTokLocs.size() to factory!
|
2007-03-13 22:37:02 +00:00
|
|
|
return new StringLiteral(Literal.GetString(), Literal.GetStringLength(),
|
2007-10-15 02:50:23 +00:00
|
|
|
Literal.AnyWide, t,
|
|
|
|
StringToks[0].getLocation(),
|
2007-05-17 21:49:33 +00:00
|
|
|
StringToks[NumStringToks-1].getLocation());
|
2006-11-10 05:03:26 +00:00
|
|
|
}
|
|
|
|
|
2006-11-10 05:29:30 +00:00
|
|
|
|
2007-09-15 18:49:24 +00:00
|
|
|
/// ActOnIdentifierExpr - The parser read an identifier in expression context,
|
2006-11-20 06:49:47 +00:00
|
|
|
/// validate it per-C99 6.5.1. HasTrailingLParen indicates whether this
|
|
|
|
/// identifier is used in an function call context.
|
2007-09-15 18:49:24 +00:00
|
|
|
Sema::ExprResult Sema::ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
|
2006-11-20 06:49:47 +00:00
|
|
|
IdentifierInfo &II,
|
|
|
|
bool HasTrailingLParen) {
|
2006-11-20 04:58:19 +00:00
|
|
|
// Could be enum-constant or decl.
|
2007-09-16 16:16:00 +00:00
|
|
|
ScopedDecl *D = LookupScopedDecl(&II, Decl::IDNS_Ordinary, Loc, S);
|
2006-11-20 04:58:19 +00:00
|
|
|
if (D == 0) {
|
2007-02-13 01:51:42 +00:00
|
|
|
// Otherwise, this could be an implicitly declared function reference (legal
|
2007-01-28 08:20:04 +00:00
|
|
|
// in C90, extension in C99).
|
2006-11-20 06:49:47 +00:00
|
|
|
if (HasTrailingLParen &&
|
|
|
|
// Not in C++.
|
2007-03-23 22:27:02 +00:00
|
|
|
!getLangOptions().CPlusPlus)
|
2006-11-20 06:49:47 +00:00
|
|
|
D = ImplicitlyDefineFunction(Loc, II, S);
|
2007-04-02 22:35:25 +00:00
|
|
|
else {
|
2006-11-20 06:49:47 +00:00
|
|
|
// If this name wasn't predeclared and if this is not a function call,
|
|
|
|
// diagnose the problem.
|
2007-03-23 22:27:02 +00:00
|
|
|
return Diag(Loc, diag::err_undeclared_var_use, II.getName());
|
2007-04-02 22:35:25 +00:00
|
|
|
}
|
2006-11-20 04:58:19 +00:00
|
|
|
}
|
2007-08-28 03:03:08 +00:00
|
|
|
if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
|
2007-08-28 18:45:29 +00:00
|
|
|
// Only create DeclRefExpr's for valid Decl's.
|
2007-08-28 20:14:24 +00:00
|
|
|
if (VD->isInvalidDecl())
|
2007-08-28 03:03:08 +00:00
|
|
|
return true;
|
2007-05-17 01:16:00 +00:00
|
|
|
return new DeclRefExpr(VD, VD->getType(), Loc);
|
2007-08-28 03:03:08 +00:00
|
|
|
}
|
2007-04-03 23:13:13 +00:00
|
|
|
if (isa<TypedefDecl>(D))
|
2007-03-23 22:27:02 +00:00
|
|
|
return Diag(Loc, diag::err_unexpected_typedef, II.getName());
|
|
|
|
|
|
|
|
assert(0 && "Invalid decl");
|
2007-07-21 04:57:45 +00:00
|
|
|
abort();
|
2006-11-20 04:58:19 +00:00
|
|
|
}
|
2006-11-10 05:29:30 +00:00
|
|
|
|
2007-09-16 03:34:24 +00:00
|
|
|
Sema::ExprResult Sema::ActOnPreDefinedExpr(SourceLocation Loc,
|
2007-07-21 05:21:51 +00:00
|
|
|
tok::TokenKind Kind) {
|
|
|
|
PreDefinedExpr::IdentType IT;
|
|
|
|
|
2006-11-10 05:29:30 +00:00
|
|
|
switch (Kind) {
|
|
|
|
default:
|
|
|
|
assert(0 && "Unknown simple primary expr!");
|
|
|
|
case tok::kw___func__: // primary-expression: __func__ [C99 6.4.2.2]
|
2007-07-21 05:21:51 +00:00
|
|
|
IT = PreDefinedExpr::Func;
|
|
|
|
break;
|
2006-11-10 05:29:30 +00:00
|
|
|
case tok::kw___FUNCTION__: // primary-expression: __FUNCTION__ [GNU]
|
2007-07-21 05:21:51 +00:00
|
|
|
IT = PreDefinedExpr::Function;
|
|
|
|
break;
|
2006-11-10 05:29:30 +00:00
|
|
|
case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU]
|
2007-07-21 05:21:51 +00:00
|
|
|
IT = PreDefinedExpr::PrettyFunction;
|
|
|
|
break;
|
2006-11-10 05:29:30 +00:00
|
|
|
}
|
2007-07-21 05:21:51 +00:00
|
|
|
|
|
|
|
// Pre-defined identifiers are always of type char *.
|
|
|
|
return new PreDefinedExpr(Loc, Context.getPointerType(Context.CharTy), IT);
|
2006-11-10 05:29:30 +00:00
|
|
|
}
|
|
|
|
|
2007-09-16 03:34:24 +00:00
|
|
|
Sema::ExprResult Sema::ActOnCharacterConstant(const Token &Tok) {
|
2007-06-15 23:05:46 +00:00
|
|
|
llvm::SmallString<16> CharBuffer;
|
2007-04-26 20:39:23 +00:00
|
|
|
CharBuffer.resize(Tok.getLength());
|
|
|
|
const char *ThisTokBegin = &CharBuffer[0];
|
|
|
|
unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin);
|
|
|
|
|
|
|
|
CharLiteralParser Literal(ThisTokBegin, ThisTokBegin+ActualLength,
|
|
|
|
Tok.getLocation(), PP);
|
|
|
|
if (Literal.hadError())
|
|
|
|
return ExprResult(true);
|
2007-05-17 01:16:00 +00:00
|
|
|
return new CharacterLiteral(Literal.getValue(), Context.IntTy,
|
|
|
|
Tok.getLocation());
|
2007-04-26 20:39:23 +00:00
|
|
|
}
|
|
|
|
|
2007-09-16 03:34:24 +00:00
|
|
|
Action::ExprResult Sema::ActOnNumericConstant(const Token &Tok) {
|
2007-03-13 20:29:44 +00:00
|
|
|
// fast path for a single digit (which is quite common). A single digit
|
|
|
|
// cannot have a trigraph, escaped newline, radix prefix, or type suffix.
|
|
|
|
if (Tok.getLength() == 1) {
|
|
|
|
const char *t = PP.getSourceManager().getCharacterData(Tok.getLocation());
|
2007-05-21 01:08:44 +00:00
|
|
|
|
2007-09-04 02:45:27 +00:00
|
|
|
unsigned IntSize = static_cast<unsigned>(
|
|
|
|
Context.getTypeSize(Context.IntTy, Tok.getLocation()));
|
2007-06-15 23:05:46 +00:00
|
|
|
return ExprResult(new IntegerLiteral(llvm::APInt(IntSize, *t-'0'),
|
|
|
|
Context.IntTy,
|
2007-05-17 01:16:00 +00:00
|
|
|
Tok.getLocation()));
|
2007-03-13 20:29:44 +00:00
|
|
|
}
|
2007-06-15 23:05:46 +00:00
|
|
|
llvm::SmallString<512> IntegerBuffer;
|
2007-03-06 01:09:46 +00:00
|
|
|
IntegerBuffer.resize(Tok.getLength());
|
|
|
|
const char *ThisTokBegin = &IntegerBuffer[0];
|
|
|
|
|
2007-05-21 01:08:44 +00:00
|
|
|
// Get the spelling of the token, which eliminates trigraphs, etc.
|
2007-03-06 01:09:46 +00:00
|
|
|
unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin);
|
2007-03-09 23:16:33 +00:00
|
|
|
NumericLiteralParser Literal(ThisTokBegin, ThisTokBegin+ActualLength,
|
2007-03-12 23:22:38 +00:00
|
|
|
Tok.getLocation(), PP);
|
2007-03-13 20:29:44 +00:00
|
|
|
if (Literal.hadError)
|
|
|
|
return ExprResult(true);
|
2007-05-21 01:08:44 +00:00
|
|
|
|
2007-08-26 03:42:43 +00:00
|
|
|
Expr *Res;
|
|
|
|
|
|
|
|
if (Literal.isFloatingLiteral()) {
|
2007-09-22 18:29:59 +00:00
|
|
|
QualType Ty;
|
|
|
|
const llvm::fltSemantics *Format;
|
|
|
|
uint64_t Size; unsigned Align;
|
|
|
|
|
|
|
|
if (Literal.isFloat) {
|
|
|
|
Ty = Context.FloatTy;
|
|
|
|
Context.Target.getFloatInfo(Size, Align, Format, Tok.getLocation());
|
|
|
|
} else if (Literal.isLong) {
|
|
|
|
Ty = Context.LongDoubleTy;
|
|
|
|
Context.Target.getLongDoubleInfo(Size, Align, Format, Tok.getLocation());
|
|
|
|
} else {
|
|
|
|
Ty = Context.DoubleTy;
|
|
|
|
Context.Target.getDoubleInfo(Size, Align, Format, Tok.getLocation());
|
|
|
|
}
|
|
|
|
|
|
|
|
Res = new FloatingLiteral(Literal.GetFloatValue(*Format), Ty,
|
|
|
|
Tok.getLocation());
|
2007-08-26 03:42:43 +00:00
|
|
|
} else if (!Literal.isIntegerLiteral()) {
|
|
|
|
return ExprResult(true);
|
|
|
|
} else {
|
2007-04-05 22:36:20 +00:00
|
|
|
QualType t;
|
2007-05-21 01:08:44 +00:00
|
|
|
|
2007-08-29 22:00:19 +00:00
|
|
|
// long long is a C99 feature.
|
|
|
|
if (!getLangOptions().C99 && !getLangOptions().CPlusPlus0x &&
|
2007-08-29 22:13:52 +00:00
|
|
|
Literal.isLongLong)
|
2007-08-29 22:00:19 +00:00
|
|
|
Diag(Tok.getLocation(), diag::ext_longlong);
|
|
|
|
|
2007-05-21 01:08:44 +00:00
|
|
|
// Get the value in the widest-possible width.
|
2007-06-15 23:05:46 +00:00
|
|
|
llvm::APInt ResultVal(Context.Target.getIntMaxTWidth(Tok.getLocation()), 0);
|
2007-05-21 01:08:44 +00:00
|
|
|
|
|
|
|
if (Literal.GetIntegerValue(ResultVal)) {
|
|
|
|
// If this value didn't fit into uintmax_t, warn and force to ull.
|
|
|
|
Diag(Tok.getLocation(), diag::warn_integer_too_large);
|
|
|
|
t = Context.UnsignedLongLongTy;
|
2007-07-14 01:29:45 +00:00
|
|
|
assert(Context.getTypeSize(t, Tok.getLocation()) ==
|
2007-05-21 01:08:44 +00:00
|
|
|
ResultVal.getBitWidth() && "long long is not intmax_t?");
|
2007-03-06 01:09:46 +00:00
|
|
|
} else {
|
2007-05-21 01:08:44 +00:00
|
|
|
// If this value fits into a ULL, try to figure out what else it fits into
|
|
|
|
// according to the rules of C99 6.4.4.1p5.
|
|
|
|
|
|
|
|
// Octal, Hexadecimal, and integers with a U suffix are allowed to
|
|
|
|
// be an unsigned int.
|
|
|
|
bool AllowUnsigned = Literal.isUnsigned || Literal.getRadix() != 10;
|
|
|
|
|
|
|
|
// Check from smallest to largest, picking the smallest type we can.
|
2007-08-23 21:58:08 +00:00
|
|
|
if (!Literal.isLong && !Literal.isLongLong) {
|
|
|
|
// Are int/unsigned possibilities?
|
2007-09-04 02:45:27 +00:00
|
|
|
unsigned IntSize = static_cast<unsigned>(
|
|
|
|
Context.getTypeSize(Context.IntTy,Tok.getLocation()));
|
2007-05-21 01:08:44 +00:00
|
|
|
// Does it fit in a unsigned int?
|
|
|
|
if (ResultVal.isIntN(IntSize)) {
|
|
|
|
// Does it fit in a signed int?
|
|
|
|
if (!Literal.isUnsigned && ResultVal[IntSize-1] == 0)
|
|
|
|
t = Context.IntTy;
|
|
|
|
else if (AllowUnsigned)
|
|
|
|
t = Context.UnsignedIntTy;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!t.isNull())
|
|
|
|
ResultVal.trunc(IntSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Are long/unsigned long possibilities?
|
|
|
|
if (t.isNull() && !Literal.isLongLong) {
|
2007-09-04 02:45:27 +00:00
|
|
|
unsigned LongSize = static_cast<unsigned>(
|
|
|
|
Context.getTypeSize(Context.LongTy, Tok.getLocation()));
|
2007-05-21 01:08:44 +00:00
|
|
|
|
|
|
|
// Does it fit in a unsigned long?
|
|
|
|
if (ResultVal.isIntN(LongSize)) {
|
|
|
|
// Does it fit in a signed long?
|
|
|
|
if (!Literal.isUnsigned && ResultVal[LongSize-1] == 0)
|
|
|
|
t = Context.LongTy;
|
|
|
|
else if (AllowUnsigned)
|
|
|
|
t = Context.UnsignedLongTy;
|
|
|
|
}
|
|
|
|
if (!t.isNull())
|
|
|
|
ResultVal.trunc(LongSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Finally, check long long if needed.
|
|
|
|
if (t.isNull()) {
|
2007-09-04 02:45:27 +00:00
|
|
|
unsigned LongLongSize = static_cast<unsigned>(
|
|
|
|
Context.getTypeSize(Context.LongLongTy, Tok.getLocation()));
|
2007-05-21 01:08:44 +00:00
|
|
|
|
|
|
|
// Does it fit in a unsigned long long?
|
|
|
|
if (ResultVal.isIntN(LongLongSize)) {
|
|
|
|
// Does it fit in a signed long long?
|
|
|
|
if (!Literal.isUnsigned && ResultVal[LongLongSize-1] == 0)
|
|
|
|
t = Context.LongLongTy;
|
|
|
|
else if (AllowUnsigned)
|
|
|
|
t = Context.UnsignedLongLongTy;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we still couldn't decide a type, we probably have something that
|
|
|
|
// does not fit in a signed long long, but has no U suffix.
|
|
|
|
if (t.isNull()) {
|
|
|
|
Diag(Tok.getLocation(), diag::warn_integer_too_large_for_signed);
|
|
|
|
t = Context.UnsignedLongLongTy;
|
|
|
|
}
|
2007-03-07 01:21:37 +00:00
|
|
|
}
|
2007-05-21 01:08:44 +00:00
|
|
|
|
2007-08-26 03:42:43 +00:00
|
|
|
Res = new IntegerLiteral(ResultVal, t, Tok.getLocation());
|
2007-03-06 01:09:46 +00:00
|
|
|
}
|
2007-08-26 03:42:43 +00:00
|
|
|
|
|
|
|
// If this is an imaginary literal, create the ImaginaryLiteral wrapper.
|
|
|
|
if (Literal.isImaginary)
|
|
|
|
Res = new ImaginaryLiteral(Res, Context.getComplexType(Res->getType()));
|
|
|
|
|
|
|
|
return Res;
|
2006-11-10 05:29:30 +00:00
|
|
|
}
|
|
|
|
|
2007-09-16 03:34:24 +00:00
|
|
|
Action::ExprResult Sema::ActOnParenExpr(SourceLocation L, SourceLocation R,
|
2006-11-10 05:29:30 +00:00
|
|
|
ExprTy *Val) {
|
2007-04-26 20:39:23 +00:00
|
|
|
Expr *e = (Expr *)Val;
|
2007-09-16 03:34:24 +00:00
|
|
|
assert((e != 0) && "ActOnParenExpr() missing expr");
|
2007-05-17 21:49:33 +00:00
|
|
|
return new ParenExpr(L, R, e);
|
2006-11-10 05:29:30 +00:00
|
|
|
}
|
|
|
|
|
2007-06-04 22:22:31 +00:00
|
|
|
/// The UsualUnaryConversions() function is *not* called by this routine.
|
2007-05-16 19:47:19 +00:00
|
|
|
/// See C99 6.3.2.1p[2-4] for more details.
|
2007-05-15 02:32:35 +00:00
|
|
|
QualType Sema::CheckSizeOfAlignOfOperand(QualType exprType,
|
|
|
|
SourceLocation OpLoc, bool isSizeof) {
|
|
|
|
// C99 6.5.3.4p1:
|
|
|
|
if (isa<FunctionType>(exprType) && isSizeof)
|
|
|
|
// alignof(function) is allowed.
|
|
|
|
Diag(OpLoc, diag::ext_sizeof_function_type);
|
|
|
|
else if (exprType->isVoidType())
|
|
|
|
Diag(OpLoc, diag::ext_sizeof_void_type, isSizeof ? "sizeof" : "__alignof");
|
|
|
|
else if (exprType->isIncompleteType()) {
|
|
|
|
Diag(OpLoc, isSizeof ? diag::err_sizeof_incomplete_type :
|
2007-05-16 18:07:12 +00:00
|
|
|
diag::err_alignof_incomplete_type,
|
|
|
|
exprType.getAsString());
|
2007-05-15 02:32:35 +00:00
|
|
|
return QualType(); // error
|
|
|
|
}
|
|
|
|
// C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
|
|
|
|
return Context.getSizeType();
|
|
|
|
}
|
|
|
|
|
2006-11-10 05:29:30 +00:00
|
|
|
Action::ExprResult Sema::
|
2007-09-16 03:34:24 +00:00
|
|
|
ActOnSizeOfAlignOfTypeExpr(SourceLocation OpLoc, bool isSizeof,
|
2007-05-17 01:16:00 +00:00
|
|
|
SourceLocation LPLoc, TypeTy *Ty,
|
|
|
|
SourceLocation RPLoc) {
|
2006-11-20 04:34:45 +00:00
|
|
|
// If error parsing type, ignore.
|
|
|
|
if (Ty == 0) return true;
|
2007-01-23 22:29:49 +00:00
|
|
|
|
|
|
|
// Verify that this is a valid expression.
|
2007-04-05 22:36:20 +00:00
|
|
|
QualType ArgTy = QualType::getFromOpaquePtr(Ty);
|
2007-01-23 22:29:49 +00:00
|
|
|
|
2007-05-15 02:32:35 +00:00
|
|
|
QualType resultType = CheckSizeOfAlignOfOperand(ArgTy, OpLoc, isSizeof);
|
|
|
|
|
|
|
|
if (resultType.isNull())
|
|
|
|
return true;
|
2007-05-17 01:16:00 +00:00
|
|
|
return new SizeOfAlignOfTypeExpr(isSizeof, ArgTy, resultType, OpLoc, RPLoc);
|
2006-11-10 05:29:30 +00:00
|
|
|
}
|
|
|
|
|
2007-08-24 21:41:10 +00:00
|
|
|
QualType Sema::CheckRealImagOperand(Expr *&V, SourceLocation Loc) {
|
2007-08-24 21:16:53 +00:00
|
|
|
DefaultFunctionArrayConversion(V);
|
|
|
|
|
2007-08-26 05:39:26 +00:00
|
|
|
// These operators return the element type of a complex type.
|
2007-08-24 21:16:53 +00:00
|
|
|
if (const ComplexType *CT = V->getType()->getAsComplexType())
|
|
|
|
return CT->getElementType();
|
2007-08-26 05:39:26 +00:00
|
|
|
|
|
|
|
// Otherwise they pass through real integer and floating point types here.
|
|
|
|
if (V->getType()->isArithmeticType())
|
|
|
|
return V->getType();
|
|
|
|
|
|
|
|
// Reject anything else.
|
|
|
|
Diag(Loc, diag::err_realimag_invalid_type, V->getType().getAsString());
|
|
|
|
return QualType();
|
2007-08-24 21:16:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-11-10 05:29:30 +00:00
|
|
|
|
2007-09-16 03:34:24 +00:00
|
|
|
Action::ExprResult Sema::ActOnPostfixUnaryOp(SourceLocation OpLoc,
|
2006-11-10 05:29:30 +00:00
|
|
|
tok::TokenKind Kind,
|
|
|
|
ExprTy *Input) {
|
|
|
|
UnaryOperator::Opcode Opc;
|
|
|
|
switch (Kind) {
|
|
|
|
default: assert(0 && "Unknown unary op!");
|
|
|
|
case tok::plusplus: Opc = UnaryOperator::PostInc; break;
|
|
|
|
case tok::minusminus: Opc = UnaryOperator::PostDec; break;
|
|
|
|
}
|
2007-05-18 22:53:50 +00:00
|
|
|
QualType result = CheckIncrementDecrementOperand((Expr *)Input, OpLoc);
|
2007-05-07 00:24:15 +00:00
|
|
|
if (result.isNull())
|
|
|
|
return true;
|
2007-05-17 01:16:00 +00:00
|
|
|
return new UnaryOperator((Expr *)Input, Opc, result, OpLoc);
|
2006-11-10 05:29:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Action::ExprResult Sema::
|
2007-09-16 03:34:24 +00:00
|
|
|
ActOnArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc,
|
2006-11-10 05:29:30 +00:00
|
|
|
ExprTy *Idx, SourceLocation RLoc) {
|
2007-07-15 23:59:53 +00:00
|
|
|
Expr *LHSExp = static_cast<Expr*>(Base), *RHSExp = static_cast<Expr*>(Idx);
|
2007-07-16 00:14:47 +00:00
|
|
|
|
|
|
|
// Perform default conversions.
|
|
|
|
DefaultFunctionArrayConversion(LHSExp);
|
|
|
|
DefaultFunctionArrayConversion(RHSExp);
|
2007-07-15 23:59:53 +00:00
|
|
|
|
2007-07-16 00:14:47 +00:00
|
|
|
QualType LHSTy = LHSExp->getType(), RHSTy = RHSExp->getType();
|
2007-03-23 22:27:02 +00:00
|
|
|
|
2007-03-28 21:49:40 +00:00
|
|
|
// C99 6.5.2.1p2: the expression e1[e2] is by definition precisely equivalent
|
2007-08-30 17:45:32 +00:00
|
|
|
// to the expression *((e1)+(e2)). This means the array "Base" may actually be
|
2007-03-23 22:27:02 +00:00
|
|
|
// in the subscript position. As a result, we need to derive the array base
|
|
|
|
// and index from the expression types.
|
2007-07-16 00:14:47 +00:00
|
|
|
Expr *BaseExpr, *IndexExpr;
|
|
|
|
QualType ResultType;
|
2007-07-31 16:53:04 +00:00
|
|
|
if (const PointerType *PTy = LHSTy->getAsPointerType()) {
|
2007-07-16 00:14:47 +00:00
|
|
|
BaseExpr = LHSExp;
|
|
|
|
IndexExpr = RHSExp;
|
|
|
|
// FIXME: need to deal with const...
|
|
|
|
ResultType = PTy->getPointeeType();
|
2007-07-31 16:53:04 +00:00
|
|
|
} else if (const PointerType *PTy = RHSTy->getAsPointerType()) {
|
2007-07-16 00:23:25 +00:00
|
|
|
// Handle the uncommon case of "123[Ptr]".
|
2007-07-16 00:14:47 +00:00
|
|
|
BaseExpr = RHSExp;
|
|
|
|
IndexExpr = LHSExp;
|
|
|
|
// FIXME: need to deal with const...
|
|
|
|
ResultType = PTy->getPointeeType();
|
2007-07-31 19:29:30 +00:00
|
|
|
} else if (const VectorType *VTy = LHSTy->getAsVectorType()) {
|
|
|
|
BaseExpr = LHSExp; // vectors: V[123]
|
2007-07-16 00:14:47 +00:00
|
|
|
IndexExpr = RHSExp;
|
2007-08-03 22:40:33 +00:00
|
|
|
|
|
|
|
// Component access limited to variables (reject vec4.rg[1]).
|
|
|
|
if (!isa<DeclRefExpr>(BaseExpr))
|
|
|
|
return Diag(LLoc, diag::err_ocuvector_component_access,
|
|
|
|
SourceRange(LLoc, RLoc));
|
2007-07-16 00:14:47 +00:00
|
|
|
// FIXME: need to deal with const...
|
|
|
|
ResultType = VTy->getElementType();
|
2007-06-09 03:47:53 +00:00
|
|
|
} else {
|
2007-07-15 23:59:53 +00:00
|
|
|
return Diag(LHSExp->getLocStart(), diag::err_typecheck_subscript_value,
|
|
|
|
RHSExp->getSourceRange());
|
2007-06-09 03:47:53 +00:00
|
|
|
}
|
2007-03-28 21:49:40 +00:00
|
|
|
// C99 6.5.2.1p1
|
2007-07-16 00:14:47 +00:00
|
|
|
if (!IndexExpr->getType()->isIntegerType())
|
|
|
|
return Diag(IndexExpr->getLocStart(), diag::err_typecheck_subscript,
|
|
|
|
IndexExpr->getSourceRange());
|
|
|
|
|
|
|
|
// C99 6.5.2.1p1: "shall have type "pointer to *object* type". In practice,
|
|
|
|
// the following check catches trying to index a pointer to a function (e.g.
|
|
|
|
// void (*)(int)). Functions are not objects in C99.
|
|
|
|
if (!ResultType->isObjectType())
|
|
|
|
return Diag(BaseExpr->getLocStart(),
|
|
|
|
diag::err_typecheck_subscript_not_object,
|
|
|
|
BaseExpr->getType().getAsString(), BaseExpr->getSourceRange());
|
2007-07-10 18:23:31 +00:00
|
|
|
|
2007-07-16 00:14:47 +00:00
|
|
|
return new ArraySubscriptExpr(LHSExp, RHSExp, ResultType, RLoc);
|
2006-11-10 05:29:30 +00:00
|
|
|
}
|
|
|
|
|
2007-07-27 22:15:19 +00:00
|
|
|
QualType Sema::
|
|
|
|
CheckOCUVectorComponent(QualType baseType, SourceLocation OpLoc,
|
|
|
|
IdentifierInfo &CompName, SourceLocation CompLoc) {
|
2007-07-31 19:29:30 +00:00
|
|
|
const OCUVectorType *vecType = baseType->getAsOCUVectorType();
|
2007-07-27 22:15:19 +00:00
|
|
|
|
|
|
|
// The vector accessor can't exceed the number of elements.
|
|
|
|
const char *compStr = CompName.getName();
|
|
|
|
if (strlen(compStr) > vecType->getNumElements()) {
|
|
|
|
Diag(OpLoc, diag::err_ocuvector_component_exceeds_length,
|
|
|
|
baseType.getAsString(), SourceRange(CompLoc));
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
// The component names must come from the same set.
|
2007-08-02 22:33:49 +00:00
|
|
|
if (vecType->getPointAccessorIdx(*compStr) != -1) {
|
|
|
|
do
|
|
|
|
compStr++;
|
|
|
|
while (*compStr && vecType->getPointAccessorIdx(*compStr) != -1);
|
|
|
|
} else if (vecType->getColorAccessorIdx(*compStr) != -1) {
|
|
|
|
do
|
|
|
|
compStr++;
|
|
|
|
while (*compStr && vecType->getColorAccessorIdx(*compStr) != -1);
|
|
|
|
} else if (vecType->getTextureAccessorIdx(*compStr) != -1) {
|
|
|
|
do
|
|
|
|
compStr++;
|
|
|
|
while (*compStr && vecType->getTextureAccessorIdx(*compStr) != -1);
|
|
|
|
}
|
2007-07-27 22:15:19 +00:00
|
|
|
|
|
|
|
if (*compStr) {
|
|
|
|
// We didn't get to the end of the string. This means the component names
|
|
|
|
// didn't come from the same set *or* we encountered an illegal name.
|
|
|
|
Diag(OpLoc, diag::err_ocuvector_component_name_illegal,
|
|
|
|
std::string(compStr,compStr+1), SourceRange(CompLoc));
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
// Each component accessor can't exceed the vector type.
|
|
|
|
compStr = CompName.getName();
|
|
|
|
while (*compStr) {
|
|
|
|
if (vecType->isAccessorWithinNumElements(*compStr))
|
|
|
|
compStr++;
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (*compStr) {
|
|
|
|
// We didn't get to the end of the string. This means a component accessor
|
|
|
|
// exceeds the number of elements in the vector.
|
|
|
|
Diag(OpLoc, diag::err_ocuvector_component_exceeds_length,
|
|
|
|
baseType.getAsString(), SourceRange(CompLoc));
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
// The component accessor looks fine - now we need to compute the actual type.
|
|
|
|
// The vector type is implied by the component accessor. For example,
|
|
|
|
// vec4.b is a float, vec4.xy is a vec2, vec4.rgb is a vec3, etc.
|
|
|
|
unsigned CompSize = strlen(CompName.getName());
|
|
|
|
if (CompSize == 1)
|
|
|
|
return vecType->getElementType();
|
2007-07-29 16:33:31 +00:00
|
|
|
|
|
|
|
QualType VT = Context.getOCUVectorType(vecType->getElementType(), CompSize);
|
|
|
|
// Now look up the TypeDefDecl from the vector type. Without this,
|
|
|
|
// diagostics look bad. We want OCU vector types to appear built-in.
|
|
|
|
for (unsigned i = 0, e = OCUVectorDecls.size(); i != e; ++i) {
|
|
|
|
if (OCUVectorDecls[i]->getUnderlyingType() == VT)
|
|
|
|
return Context.getTypedefType(OCUVectorDecls[i]);
|
|
|
|
}
|
|
|
|
return VT; // should never get here (a typedef type should always be found).
|
2007-07-27 22:15:19 +00:00
|
|
|
}
|
|
|
|
|
2006-11-10 05:29:30 +00:00
|
|
|
Action::ExprResult Sema::
|
2007-09-16 03:34:24 +00:00
|
|
|
ActOnMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
|
2006-11-10 05:29:30 +00:00
|
|
|
tok::TokenKind OpKind, SourceLocation MemberLoc,
|
|
|
|
IdentifierInfo &Member) {
|
2007-07-26 03:11:44 +00:00
|
|
|
Expr *BaseExpr = static_cast<Expr *>(Base);
|
|
|
|
assert(BaseExpr && "no record expression");
|
2007-04-01 01:41:35 +00:00
|
|
|
|
2007-07-26 03:11:44 +00:00
|
|
|
QualType BaseType = BaseExpr->getType();
|
|
|
|
assert(!BaseType.isNull() && "no type for member expression");
|
2007-04-01 01:41:35 +00:00
|
|
|
|
2007-03-23 22:27:02 +00:00
|
|
|
if (OpKind == tok::arrow) {
|
2007-07-31 16:53:04 +00:00
|
|
|
if (const PointerType *PT = BaseType->getAsPointerType())
|
2007-07-26 03:11:44 +00:00
|
|
|
BaseType = PT->getPointeeType();
|
|
|
|
else
|
|
|
|
return Diag(OpLoc, diag::err_typecheck_member_reference_arrow,
|
|
|
|
SourceRange(MemberLoc));
|
2007-03-23 22:27:02 +00:00
|
|
|
}
|
2007-07-27 22:15:19 +00:00
|
|
|
// The base type is either a record or an OCUVectorType.
|
2007-07-31 19:29:30 +00:00
|
|
|
if (const RecordType *RTy = BaseType->getAsRecordType()) {
|
2007-07-26 03:11:44 +00:00
|
|
|
RecordDecl *RDecl = RTy->getDecl();
|
|
|
|
if (RTy->isIncompleteType())
|
|
|
|
return Diag(OpLoc, diag::err_typecheck_incomplete_tag, RDecl->getName(),
|
|
|
|
BaseExpr->getSourceRange());
|
|
|
|
// The record definition is complete, now make sure the member is valid.
|
2007-07-27 22:15:19 +00:00
|
|
|
FieldDecl *MemberDecl = RDecl->getMember(&Member);
|
|
|
|
if (!MemberDecl)
|
2007-07-26 03:11:44 +00:00
|
|
|
return Diag(OpLoc, diag::err_typecheck_no_member, Member.getName(),
|
|
|
|
SourceRange(MemberLoc));
|
2007-07-27 22:15:19 +00:00
|
|
|
return new MemberExpr(BaseExpr, OpKind==tok::arrow, MemberDecl, MemberLoc);
|
|
|
|
} else if (BaseType->isOCUVectorType() && OpKind == tok::period) {
|
2007-08-03 22:40:33 +00:00
|
|
|
// Component access limited to variables (reject vec4.rg.g).
|
|
|
|
if (!isa<DeclRefExpr>(BaseExpr))
|
|
|
|
return Diag(OpLoc, diag::err_ocuvector_component_access,
|
|
|
|
SourceRange(MemberLoc));
|
2007-07-27 22:15:19 +00:00
|
|
|
QualType ret = CheckOCUVectorComponent(BaseType, OpLoc, Member, MemberLoc);
|
|
|
|
if (ret.isNull())
|
|
|
|
return true;
|
2007-08-03 17:31:20 +00:00
|
|
|
return new OCUVectorElementExpr(ret, BaseExpr, Member, MemberLoc);
|
2007-07-26 03:11:44 +00:00
|
|
|
} else
|
|
|
|
return Diag(OpLoc, diag::err_typecheck_member_reference_structUnion,
|
|
|
|
SourceRange(MemberLoc));
|
2006-11-10 05:29:30 +00:00
|
|
|
}
|
|
|
|
|
2007-09-16 03:34:24 +00:00
|
|
|
/// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
|
2006-11-10 05:29:30 +00:00
|
|
|
/// This provides the location of the left/right parens and a list of comma
|
|
|
|
/// locations.
|
|
|
|
Action::ExprResult Sema::
|
2007-09-16 03:34:24 +00:00
|
|
|
ActOnCallExpr(ExprTy *fn, SourceLocation LParenLoc,
|
2007-07-21 03:03:59 +00:00
|
|
|
ExprTy **args, unsigned NumArgsInCall,
|
2006-11-10 05:29:30 +00:00
|
|
|
SourceLocation *CommaLocs, SourceLocation RParenLoc) {
|
2007-07-21 03:03:59 +00:00
|
|
|
Expr *Fn = static_cast<Expr *>(fn);
|
|
|
|
Expr **Args = reinterpret_cast<Expr**>(args);
|
|
|
|
assert(Fn && "no function call expression");
|
2007-05-28 19:25:56 +00:00
|
|
|
|
2007-07-21 03:03:59 +00:00
|
|
|
UsualUnaryConversions(Fn);
|
|
|
|
QualType funcType = Fn->getType();
|
2007-04-26 20:39:23 +00:00
|
|
|
|
2007-06-06 05:14:05 +00:00
|
|
|
// C99 6.5.2.2p1 - "The expression that denotes the called function shall have
|
|
|
|
// type pointer to function".
|
2007-07-31 21:27:01 +00:00
|
|
|
const PointerType *PT = funcType->getAsPointerType();
|
2007-06-06 05:14:05 +00:00
|
|
|
if (PT == 0)
|
2007-07-21 03:03:59 +00:00
|
|
|
return Diag(Fn->getLocStart(), diag::err_typecheck_call_not_function,
|
|
|
|
SourceRange(Fn->getLocStart(), RParenLoc));
|
2007-06-06 05:05:41 +00:00
|
|
|
|
2007-07-31 21:27:01 +00:00
|
|
|
const FunctionType *funcT = PT->getPointeeType()->getAsFunctionType();
|
2007-06-06 05:14:05 +00:00
|
|
|
if (funcT == 0)
|
2007-07-21 03:03:59 +00:00
|
|
|
return Diag(Fn->getLocStart(), diag::err_typecheck_call_not_function,
|
|
|
|
SourceRange(Fn->getLocStart(), RParenLoc));
|
2007-05-08 22:18:00 +00:00
|
|
|
|
2007-05-03 21:03:48 +00:00
|
|
|
// If a prototype isn't declared, the parser implicitly defines a func decl
|
|
|
|
QualType resultType = funcT->getResultType();
|
|
|
|
|
|
|
|
if (const FunctionTypeProto *proto = dyn_cast<FunctionTypeProto>(funcT)) {
|
|
|
|
// C99 6.5.2.2p7 - the arguments are implicitly converted, as if by
|
|
|
|
// assignment, to the types of the corresponding parameter, ...
|
|
|
|
|
|
|
|
unsigned NumArgsInProto = proto->getNumArgs();
|
2007-05-08 22:18:00 +00:00
|
|
|
unsigned NumArgsToCheck = NumArgsInCall;
|
2007-05-03 21:03:48 +00:00
|
|
|
|
2007-05-08 22:18:00 +00:00
|
|
|
if (NumArgsInCall < NumArgsInProto)
|
2007-05-30 04:20:12 +00:00
|
|
|
Diag(RParenLoc, diag::err_typecheck_call_too_few_args,
|
2007-07-21 03:03:59 +00:00
|
|
|
Fn->getSourceRange());
|
2007-05-08 22:18:00 +00:00
|
|
|
else if (NumArgsInCall > NumArgsInProto) {
|
2007-05-28 19:25:56 +00:00
|
|
|
if (!proto->isVariadic()) {
|
2007-07-21 03:09:58 +00:00
|
|
|
Diag(Args[NumArgsInProto]->getLocStart(),
|
2007-07-21 03:03:59 +00:00
|
|
|
diag::err_typecheck_call_too_many_args, Fn->getSourceRange(),
|
2007-07-21 03:09:58 +00:00
|
|
|
SourceRange(Args[NumArgsInProto]->getLocStart(),
|
|
|
|
Args[NumArgsInCall-1]->getLocEnd()));
|
2007-05-28 19:25:56 +00:00
|
|
|
}
|
2007-05-08 22:18:00 +00:00
|
|
|
NumArgsToCheck = NumArgsInProto;
|
2007-05-03 21:03:48 +00:00
|
|
|
}
|
|
|
|
// Continue to check argument types (even if we have too few/many args).
|
2007-05-08 22:18:00 +00:00
|
|
|
for (unsigned i = 0; i < NumArgsToCheck; i++) {
|
2007-07-21 03:03:59 +00:00
|
|
|
Expr *argExpr = Args[i];
|
2007-09-16 03:34:24 +00:00
|
|
|
assert(argExpr && "ActOnCallExpr(): missing argument expression");
|
2007-05-28 19:25:56 +00:00
|
|
|
|
2007-05-03 21:03:48 +00:00
|
|
|
QualType lhsType = proto->getArgType(i);
|
2007-05-28 19:25:56 +00:00
|
|
|
QualType rhsType = argExpr->getType();
|
2007-07-24 21:46:40 +00:00
|
|
|
|
2007-07-25 20:45:33 +00:00
|
|
|
// If necessary, apply function/array conversion. C99 6.7.5.3p[7,8].
|
2007-07-31 19:29:30 +00:00
|
|
|
if (const ArrayType *ary = lhsType->getAsArrayType())
|
2007-07-24 21:46:40 +00:00
|
|
|
lhsType = Context.getPointerType(ary->getElementType());
|
2007-07-25 20:45:33 +00:00
|
|
|
else if (lhsType->isFunctionType())
|
2007-07-24 21:46:40 +00:00
|
|
|
lhsType = Context.getPointerType(lhsType);
|
|
|
|
|
2007-07-13 23:32:42 +00:00
|
|
|
AssignmentCheckResult result = CheckSingleAssignmentConstraints(lhsType,
|
|
|
|
argExpr);
|
2007-08-24 22:33:52 +00:00
|
|
|
if (Args[i] != argExpr) // The expression was converted.
|
|
|
|
Args[i] = argExpr; // Make sure we store the converted expression.
|
2007-05-29 14:23:36 +00:00
|
|
|
SourceLocation l = argExpr->getLocStart();
|
2007-05-03 21:03:48 +00:00
|
|
|
|
|
|
|
// decode the result (notice that AST's are still created for extensions).
|
|
|
|
switch (result) {
|
|
|
|
case Compatible:
|
|
|
|
break;
|
|
|
|
case PointerFromInt:
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
// check for null pointer constant (C99 6.3.2.3p3)
|
2007-07-15 23:26:56 +00:00
|
|
|
if (!argExpr->isNullPointerConstant(Context)) {
|
2007-05-30 04:20:12 +00:00
|
|
|
Diag(l, diag::ext_typecheck_passing_pointer_int,
|
|
|
|
lhsType.getAsString(), rhsType.getAsString(),
|
2007-07-21 03:03:59 +00:00
|
|
|
Fn->getSourceRange(), argExpr->getSourceRange());
|
2007-05-30 00:06:37 +00:00
|
|
|
}
|
2007-05-03 21:03:48 +00:00
|
|
|
break;
|
|
|
|
case IntFromPointer:
|
2007-05-30 04:20:12 +00:00
|
|
|
Diag(l, diag::ext_typecheck_passing_pointer_int,
|
|
|
|
lhsType.getAsString(), rhsType.getAsString(),
|
2007-07-21 03:03:59 +00:00
|
|
|
Fn->getSourceRange(), argExpr->getSourceRange());
|
2007-05-03 21:03:48 +00:00
|
|
|
break;
|
|
|
|
case IncompatiblePointer:
|
2007-05-28 19:25:56 +00:00
|
|
|
Diag(l, diag::ext_typecheck_passing_incompatible_pointer,
|
2007-05-30 00:06:37 +00:00
|
|
|
rhsType.getAsString(), lhsType.getAsString(),
|
2007-07-21 03:03:59 +00:00
|
|
|
Fn->getSourceRange(), argExpr->getSourceRange());
|
2007-05-03 21:03:48 +00:00
|
|
|
break;
|
2007-05-11 04:00:31 +00:00
|
|
|
case CompatiblePointerDiscardsQualifiers:
|
2007-05-30 00:06:37 +00:00
|
|
|
Diag(l, diag::ext_typecheck_passing_discards_qualifiers,
|
|
|
|
rhsType.getAsString(), lhsType.getAsString(),
|
2007-07-21 03:03:59 +00:00
|
|
|
Fn->getSourceRange(), argExpr->getSourceRange());
|
2007-05-11 04:00:31 +00:00
|
|
|
break;
|
2007-05-03 21:03:48 +00:00
|
|
|
case Incompatible:
|
2007-05-28 19:25:56 +00:00
|
|
|
return Diag(l, diag::err_typecheck_passing_incompatible,
|
|
|
|
rhsType.getAsString(), lhsType.getAsString(),
|
2007-07-21 03:03:59 +00:00
|
|
|
Fn->getSourceRange(), argExpr->getSourceRange());
|
2007-05-03 21:03:48 +00:00
|
|
|
}
|
|
|
|
}
|
2007-08-28 23:30:39 +00:00
|
|
|
if (NumArgsInCall > NumArgsInProto && proto->isVariadic()) {
|
|
|
|
// Promote the arguments (C99 6.5.2.2p7).
|
|
|
|
for (unsigned i = NumArgsInProto; i < NumArgsInCall; i++) {
|
|
|
|
Expr *argExpr = Args[i];
|
2007-09-16 03:34:24 +00:00
|
|
|
assert(argExpr && "ActOnCallExpr(): missing argument expression");
|
2007-08-28 23:30:39 +00:00
|
|
|
|
|
|
|
DefaultArgumentPromotion(argExpr);
|
|
|
|
if (Args[i] != argExpr) // The expression was converted.
|
|
|
|
Args[i] = argExpr; // Make sure we store the converted expression.
|
|
|
|
}
|
|
|
|
} else if (NumArgsInCall != NumArgsInProto && !proto->isVariadic()) {
|
|
|
|
// Even if the types checked, bail if the number of arguments don't match.
|
2007-05-08 22:18:00 +00:00
|
|
|
return true;
|
2007-08-28 23:30:39 +00:00
|
|
|
}
|
|
|
|
} else if (isa<FunctionTypeNoProto>(funcT)) {
|
|
|
|
// Promote the arguments (C99 6.5.2.2p6).
|
|
|
|
for (unsigned i = 0; i < NumArgsInCall; i++) {
|
|
|
|
Expr *argExpr = Args[i];
|
2007-09-16 03:34:24 +00:00
|
|
|
assert(argExpr && "ActOnCallExpr(): missing argument expression");
|
2007-08-28 23:30:39 +00:00
|
|
|
|
|
|
|
DefaultArgumentPromotion(argExpr);
|
|
|
|
if (Args[i] != argExpr) // The expression was converted.
|
|
|
|
Args[i] = argExpr; // Make sure we store the converted expression.
|
|
|
|
}
|
2007-04-26 20:39:23 +00:00
|
|
|
}
|
2007-08-10 20:18:51 +00:00
|
|
|
// Do special checking on direct calls to functions.
|
|
|
|
if (ImplicitCastExpr *IcExpr = dyn_cast<ImplicitCastExpr>(Fn))
|
|
|
|
if (DeclRefExpr *DRExpr = dyn_cast<DeclRefExpr>(IcExpr->getSubExpr()))
|
|
|
|
if (FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRExpr->getDecl()))
|
2007-08-30 17:45:32 +00:00
|
|
|
if (CheckFunctionCall(Fn, LParenLoc, RParenLoc, FDecl, Args,
|
|
|
|
NumArgsInCall))
|
2007-08-17 05:31:46 +00:00
|
|
|
return true;
|
2007-08-10 20:18:51 +00:00
|
|
|
|
2007-07-21 03:03:59 +00:00
|
|
|
return new CallExpr(Fn, Args, NumArgsInCall, resultType, RParenLoc);
|
2006-11-10 05:29:30 +00:00
|
|
|
}
|
|
|
|
|
2007-07-19 01:06:55 +00:00
|
|
|
Action::ExprResult Sema::
|
2007-09-16 03:34:24 +00:00
|
|
|
ActOnCompoundLiteral(SourceLocation LParenLoc, TypeTy *Ty,
|
2007-07-19 21:32:11 +00:00
|
|
|
SourceLocation RParenLoc, ExprTy *InitExpr) {
|
2007-09-16 03:34:24 +00:00
|
|
|
assert((Ty != 0) && "ActOnCompoundLiteral(): missing type");
|
2007-07-19 01:06:55 +00:00
|
|
|
QualType literalType = QualType::getFromOpaquePtr(Ty);
|
2007-07-19 21:32:11 +00:00
|
|
|
// FIXME: put back this assert when initializers are worked out.
|
2007-09-16 03:34:24 +00:00
|
|
|
//assert((InitExpr != 0) && "ActOnCompoundLiteral(): missing expression");
|
2007-07-19 21:32:11 +00:00
|
|
|
Expr *literalExpr = static_cast<Expr*>(InitExpr);
|
2007-07-19 01:06:55 +00:00
|
|
|
|
|
|
|
// FIXME: add semantic analysis (C99 6.5.2.5).
|
2007-07-19 21:32:11 +00:00
|
|
|
return new CompoundLiteralExpr(literalType, literalExpr);
|
2007-07-19 01:06:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Action::ExprResult Sema::
|
2007-09-16 03:34:24 +00:00
|
|
|
ActOnInitList(SourceLocation LBraceLoc, ExprTy **initlist, unsigned NumInit,
|
2007-08-31 04:56:16 +00:00
|
|
|
SourceLocation RBraceLoc) {
|
2007-09-02 02:04:30 +00:00
|
|
|
Expr **InitList = reinterpret_cast<Expr**>(initlist);
|
2007-08-31 04:56:16 +00:00
|
|
|
|
2007-09-15 18:49:24 +00:00
|
|
|
// Semantic analysis for initializers is done by ActOnDeclarator() and
|
2007-09-03 01:24:23 +00:00
|
|
|
// CheckInitializer() - it requires knowledge of the object being intialized.
|
2007-08-31 04:56:16 +00:00
|
|
|
|
2007-09-02 20:30:18 +00:00
|
|
|
InitListExpr *e = new InitListExpr(LBraceLoc, InitList, NumInit, RBraceLoc);
|
|
|
|
e->setType(Context.VoidTy); // FIXME: just a place holder for now.
|
|
|
|
return e;
|
2007-07-19 01:06:55 +00:00
|
|
|
}
|
|
|
|
|
2006-11-10 05:29:30 +00:00
|
|
|
Action::ExprResult Sema::
|
2007-09-16 03:34:24 +00:00
|
|
|
ActOnCastExpr(SourceLocation LParenLoc, TypeTy *Ty,
|
2006-11-10 05:29:30 +00:00
|
|
|
SourceLocation RParenLoc, ExprTy *Op) {
|
2007-09-16 03:34:24 +00:00
|
|
|
assert((Ty != 0) && (Op != 0) && "ActOnCastExpr(): missing type or expr");
|
2007-07-16 23:25:18 +00:00
|
|
|
|
|
|
|
Expr *castExpr = static_cast<Expr*>(Op);
|
|
|
|
QualType castType = QualType::getFromOpaquePtr(Ty);
|
|
|
|
|
2007-08-31 00:32:44 +00:00
|
|
|
UsualUnaryConversions(castExpr);
|
|
|
|
|
2007-07-18 16:00:06 +00:00
|
|
|
// C99 6.5.4p2: the cast type needs to be void or scalar and the expression
|
|
|
|
// type needs to be scalar.
|
|
|
|
if (!castType->isScalarType() && !castType->isVoidType()) {
|
2007-07-16 23:25:18 +00:00
|
|
|
return Diag(LParenLoc, diag::err_typecheck_cond_expect_scalar,
|
|
|
|
castType.getAsString(), SourceRange(LParenLoc, RParenLoc));
|
|
|
|
}
|
|
|
|
if (!castExpr->getType()->isScalarType()) {
|
|
|
|
return Diag(castExpr->getLocStart(),
|
|
|
|
diag::err_typecheck_expect_scalar_operand,
|
|
|
|
castExpr->getType().getAsString(), castExpr->getSourceRange());
|
|
|
|
}
|
|
|
|
return new CastExpr(castType, castExpr, LParenLoc);
|
2006-11-10 05:29:30 +00:00
|
|
|
}
|
|
|
|
|
2007-05-15 20:29:32 +00:00
|
|
|
inline QualType Sema::CheckConditionalOperands( // C99 6.5.15
|
2007-07-13 16:58:59 +00:00
|
|
|
Expr *&cond, Expr *&lex, Expr *&rex, SourceLocation questionLoc) {
|
2007-07-16 21:54:35 +00:00
|
|
|
UsualUnaryConversions(cond);
|
|
|
|
UsualUnaryConversions(lex);
|
|
|
|
UsualUnaryConversions(rex);
|
|
|
|
QualType condT = cond->getType();
|
|
|
|
QualType lexT = lex->getType();
|
|
|
|
QualType rexT = rex->getType();
|
|
|
|
|
2007-05-16 19:47:19 +00:00
|
|
|
// first, check the condition.
|
2007-07-13 16:58:59 +00:00
|
|
|
if (!condT->isScalarType()) { // C99 6.5.15p2
|
|
|
|
Diag(cond->getLocStart(), diag::err_typecheck_cond_expect_scalar,
|
|
|
|
condT.getAsString());
|
2007-05-16 19:47:19 +00:00
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
// now check the two expressions.
|
2007-07-17 00:58:39 +00:00
|
|
|
if (lexT->isArithmeticType() && rexT->isArithmeticType()) { // C99 6.5.15p3,5
|
|
|
|
UsualArithmeticConversions(lex, rex);
|
|
|
|
return lex->getType();
|
|
|
|
}
|
2007-07-31 21:27:01 +00:00
|
|
|
if (const RecordType *LHSRT = lexT->getAsRecordType()) { // C99 6.5.15p3
|
|
|
|
if (const RecordType *RHSRT = rexT->getAsRecordType()) {
|
|
|
|
|
2007-08-30 17:45:32 +00:00
|
|
|
if (LHSRT->getDecl()->getIdentifier() ==RHSRT->getDecl()->getIdentifier())
|
2007-07-31 21:27:01 +00:00
|
|
|
return lexT;
|
|
|
|
|
2007-05-16 19:47:19 +00:00
|
|
|
Diag(questionLoc, diag::err_typecheck_cond_incompatible_operands,
|
2007-07-13 16:58:59 +00:00
|
|
|
lexT.getAsString(), rexT.getAsString(),
|
|
|
|
lex->getSourceRange(), rex->getSourceRange());
|
2007-05-16 19:47:19 +00:00
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
}
|
2007-07-15 23:26:56 +00:00
|
|
|
// C99 6.5.15p3
|
|
|
|
if (lexT->isPointerType() && rex->isNullPointerConstant(Context))
|
2007-07-13 16:58:59 +00:00
|
|
|
return lexT;
|
2007-07-15 23:26:56 +00:00
|
|
|
if (rexT->isPointerType() && lex->isNullPointerConstant(Context))
|
2007-07-13 16:58:59 +00:00
|
|
|
return rexT;
|
2007-05-20 19:46:53 +00:00
|
|
|
|
2007-07-31 21:27:01 +00:00
|
|
|
if (const PointerType *LHSPT = lexT->getAsPointerType()) { // C99 6.5.15p3,6
|
|
|
|
if (const PointerType *RHSPT = rexT->getAsPointerType()) {
|
|
|
|
// get the "pointed to" types
|
|
|
|
QualType lhptee = LHSPT->getPointeeType();
|
|
|
|
QualType rhptee = RHSPT->getPointeeType();
|
|
|
|
|
|
|
|
// ignore qualifiers on void (C99 6.5.15p3, clause 6)
|
|
|
|
if (lhptee->isVoidType() &&
|
|
|
|
(rhptee->isObjectType() || rhptee->isIncompleteType()))
|
|
|
|
return lexT;
|
|
|
|
if (rhptee->isVoidType() &&
|
|
|
|
(lhptee->isObjectType() || lhptee->isIncompleteType()))
|
|
|
|
return rexT;
|
|
|
|
|
|
|
|
if (!Type::typesAreCompatible(lhptee.getUnqualifiedType(),
|
|
|
|
rhptee.getUnqualifiedType())) {
|
|
|
|
Diag(questionLoc, diag::ext_typecheck_cond_incompatible_pointers,
|
|
|
|
lexT.getAsString(), rexT.getAsString(),
|
|
|
|
lex->getSourceRange(), rex->getSourceRange());
|
|
|
|
return lexT; // FIXME: this is an _ext - is this return o.k?
|
|
|
|
}
|
|
|
|
// The pointer types are compatible.
|
2007-08-30 17:45:32 +00:00
|
|
|
// C99 6.5.15p6: If both operands are pointers to compatible types *or* to
|
|
|
|
// differently qualified versions of compatible types, the result type is
|
|
|
|
// a pointer to an appropriately qualified version of the *composite*
|
|
|
|
// type.
|
2007-07-31 21:27:01 +00:00
|
|
|
return lexT; // FIXME: Need to return the composite type.
|
2007-05-16 19:47:19 +00:00
|
|
|
}
|
|
|
|
}
|
2007-07-31 21:27:01 +00:00
|
|
|
|
2007-07-13 16:58:59 +00:00
|
|
|
if (lexT->isVoidType() && rexT->isVoidType()) // C99 6.5.15p3
|
|
|
|
return lexT;
|
2007-05-16 19:47:19 +00:00
|
|
|
|
|
|
|
Diag(questionLoc, diag::err_typecheck_cond_incompatible_operands,
|
2007-07-13 16:58:59 +00:00
|
|
|
lexT.getAsString(), rexT.getAsString(),
|
|
|
|
lex->getSourceRange(), rex->getSourceRange());
|
2007-05-16 19:47:19 +00:00
|
|
|
return QualType();
|
2007-05-15 20:29:32 +00:00
|
|
|
}
|
|
|
|
|
2007-09-16 03:34:24 +00:00
|
|
|
/// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null
|
2006-11-10 05:29:30 +00:00
|
|
|
/// in the case of a the GNU conditional expr extension.
|
2007-09-16 03:34:24 +00:00
|
|
|
Action::ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
|
2006-11-10 05:29:30 +00:00
|
|
|
SourceLocation ColonLoc,
|
|
|
|
ExprTy *Cond, ExprTy *LHS,
|
|
|
|
ExprTy *RHS) {
|
2007-07-16 21:39:03 +00:00
|
|
|
Expr *CondExpr = (Expr *) Cond;
|
|
|
|
Expr *LHSExpr = (Expr *) LHS, *RHSExpr = (Expr *) RHS;
|
|
|
|
QualType result = CheckConditionalOperands(CondExpr, LHSExpr,
|
|
|
|
RHSExpr, QuestionLoc);
|
2007-05-15 20:29:32 +00:00
|
|
|
if (result.isNull())
|
|
|
|
return true;
|
2007-07-16 21:39:03 +00:00
|
|
|
return new ConditionalOperator(CondExpr, LHSExpr, RHSExpr, result);
|
2006-11-10 05:29:30 +00:00
|
|
|
}
|
|
|
|
|
2007-07-15 02:02:06 +00:00
|
|
|
// promoteExprToType - a helper function to ensure we create exactly one
|
|
|
|
// ImplicitCastExpr. As a convenience (to the caller), we return the type.
|
2007-07-17 00:58:39 +00:00
|
|
|
static void promoteExprToType(Expr *&expr, QualType type) {
|
2007-07-15 02:02:06 +00:00
|
|
|
if (ImplicitCastExpr *impCast = dyn_cast<ImplicitCastExpr>(expr))
|
|
|
|
impCast->setType(type);
|
|
|
|
else
|
|
|
|
expr = new ImplicitCastExpr(type, expr);
|
2007-07-17 00:58:39 +00:00
|
|
|
return;
|
2007-07-15 02:02:06 +00:00
|
|
|
}
|
|
|
|
|
2007-08-28 23:30:39 +00:00
|
|
|
/// DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that
|
|
|
|
/// do not have a prototype. Integer promotions are performed on each
|
|
|
|
/// argument, and arguments that have type float are promoted to double.
|
|
|
|
void Sema::DefaultArgumentPromotion(Expr *&expr) {
|
|
|
|
QualType t = expr->getType();
|
|
|
|
assert(!t.isNull() && "DefaultArgumentPromotion - missing type");
|
|
|
|
|
|
|
|
if (t->isPromotableIntegerType()) // C99 6.3.1.1p2
|
|
|
|
promoteExprToType(expr, Context.IntTy);
|
|
|
|
if (t == Context.FloatTy)
|
|
|
|
promoteExprToType(expr, Context.DoubleTy);
|
|
|
|
}
|
|
|
|
|
2007-07-15 02:02:06 +00:00
|
|
|
/// DefaultFunctionArrayConversion (C99 6.3.2.1p3, C99 6.3.2.1p4).
|
2007-07-16 21:54:35 +00:00
|
|
|
void Sema::DefaultFunctionArrayConversion(Expr *&e) {
|
2007-07-15 02:02:06 +00:00
|
|
|
QualType t = e->getType();
|
2007-07-13 23:32:42 +00:00
|
|
|
assert(!t.isNull() && "DefaultFunctionArrayConversion - missing type");
|
2007-07-17 03:52:31 +00:00
|
|
|
|
2007-07-31 16:56:34 +00:00
|
|
|
if (const ReferenceType *ref = t->getAsReferenceType()) {
|
2007-07-17 04:16:47 +00:00
|
|
|
promoteExprToType(e, ref->getReferenceeType()); // C++ [expr]
|
|
|
|
t = e->getType();
|
|
|
|
}
|
2007-07-15 02:02:06 +00:00
|
|
|
if (t->isFunctionType())
|
2007-07-16 21:54:35 +00:00
|
|
|
promoteExprToType(e, Context.getPointerType(t));
|
2007-07-31 19:29:30 +00:00
|
|
|
else if (const ArrayType *ary = t->getAsArrayType())
|
2007-07-16 21:54:35 +00:00
|
|
|
promoteExprToType(e, Context.getPointerType(ary->getElementType()));
|
2007-06-04 22:22:31 +00:00
|
|
|
}
|
|
|
|
|
2007-04-24 00:23:05 +00:00
|
|
|
/// UsualUnaryConversion - Performs various conversions that are common to most
|
|
|
|
/// operators (C99 6.3). The conversions of array and function types are
|
|
|
|
/// sometimes surpressed. For example, the array->pointer conversion doesn't
|
|
|
|
/// apply if the array is an argument to the sizeof or address (&) operators.
|
|
|
|
/// In these instances, this routine should *not* be called.
|
2007-07-16 21:54:35 +00:00
|
|
|
void Sema::UsualUnaryConversions(Expr *&expr) {
|
2007-07-13 16:58:59 +00:00
|
|
|
QualType t = expr->getType();
|
2007-06-04 22:22:31 +00:00
|
|
|
assert(!t.isNull() && "UsualUnaryConversions - missing type");
|
2007-04-20 22:26:17 +00:00
|
|
|
|
2007-07-31 16:56:34 +00:00
|
|
|
if (const ReferenceType *ref = t->getAsReferenceType()) {
|
2007-07-17 04:16:47 +00:00
|
|
|
promoteExprToType(expr, ref->getReferenceeType()); // C++ [expr]
|
|
|
|
t = expr->getType();
|
|
|
|
}
|
2007-07-15 02:02:06 +00:00
|
|
|
if (t->isPromotableIntegerType()) // C99 6.3.1.1p2
|
2007-07-16 21:54:35 +00:00
|
|
|
promoteExprToType(expr, Context.IntTy);
|
|
|
|
else
|
|
|
|
DefaultFunctionArrayConversion(expr);
|
2007-04-24 00:23:05 +00:00
|
|
|
}
|
|
|
|
|
2007-08-30 17:45:32 +00:00
|
|
|
/// UsualArithmeticConversions - Performs various conversions that are common to
|
2007-04-24 00:23:05 +00:00
|
|
|
/// binary operators (C99 6.3.1.8). If both operands aren't arithmetic, this
|
|
|
|
/// routine returns the first non-arithmetic type found. The client is
|
|
|
|
/// responsible for emitting appropriate error diagnostics.
|
2007-08-24 19:07:16 +00:00
|
|
|
QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
|
|
|
|
bool isCompAssign) {
|
2007-08-25 19:54:59 +00:00
|
|
|
if (!isCompAssign) {
|
|
|
|
UsualUnaryConversions(lhsExpr);
|
|
|
|
UsualUnaryConversions(rhsExpr);
|
|
|
|
}
|
2007-07-16 22:23:01 +00:00
|
|
|
QualType lhs = lhsExpr->getType();
|
|
|
|
QualType rhs = rhsExpr->getType();
|
2007-04-24 00:23:05 +00:00
|
|
|
|
2007-06-02 23:53:17 +00:00
|
|
|
// If both types are identical, no conversion is needed.
|
|
|
|
if (lhs == rhs)
|
2007-08-24 19:07:16 +00:00
|
|
|
return lhs;
|
2007-06-02 23:53:17 +00:00
|
|
|
|
|
|
|
// If either side is a non-arithmetic type (e.g. a pointer), we are done.
|
|
|
|
// The caller can deal with this (e.g. pointer + int).
|
2007-07-17 00:58:39 +00:00
|
|
|
if (!lhs->isArithmeticType() || !rhs->isArithmeticType())
|
2007-08-24 19:07:16 +00:00
|
|
|
return lhs;
|
2007-04-24 00:23:05 +00:00
|
|
|
|
2007-06-02 23:53:17 +00:00
|
|
|
// At this point, we have two different arithmetic types.
|
2007-04-25 01:22:31 +00:00
|
|
|
|
|
|
|
// Handle complex types first (C99 6.3.1.8p1).
|
|
|
|
if (lhs->isComplexType() || rhs->isComplexType()) {
|
|
|
|
// if we have an integer operand, the result is the complex type.
|
2007-07-17 00:58:39 +00:00
|
|
|
if (rhs->isIntegerType()) { // convert the rhs to the lhs complex type.
|
2007-08-24 19:07:16 +00:00
|
|
|
if (!isCompAssign) promoteExprToType(rhsExpr, lhs);
|
|
|
|
return lhs;
|
2007-07-17 00:58:39 +00:00
|
|
|
}
|
|
|
|
if (lhs->isIntegerType()) { // convert the lhs to the rhs complex type.
|
2007-08-24 19:07:16 +00:00
|
|
|
if (!isCompAssign) promoteExprToType(lhsExpr, rhs);
|
|
|
|
return rhs;
|
2007-07-17 00:58:39 +00:00
|
|
|
}
|
2007-08-27 01:27:54 +00:00
|
|
|
// This handles complex/complex, complex/float, or float/complex.
|
|
|
|
// When both operands are complex, the shorter operand is converted to the
|
|
|
|
// type of the longer, and that is the type of the result. This corresponds
|
|
|
|
// to what is done when combining two real floating-point operands.
|
|
|
|
// The fun begins when size promotion occur across type domains.
|
|
|
|
// From H&S 6.3.4: When one operand is complex and the other is a real
|
|
|
|
// floating-point type, the less precise type is converted, within it's
|
|
|
|
// real or complex domain, to the precision of the other type. For example,
|
|
|
|
// when combining a "long double" with a "double _Complex", the
|
|
|
|
// "double _Complex" is promoted to "long double _Complex".
|
2007-08-27 15:30:22 +00:00
|
|
|
int result = Context.compareFloatingType(lhs, rhs);
|
|
|
|
|
|
|
|
if (result > 0) { // The left side is bigger, convert rhs.
|
2007-08-27 21:32:55 +00:00
|
|
|
rhs = Context.getFloatingTypeOfSizeWithinDomain(lhs, rhs);
|
|
|
|
if (!isCompAssign)
|
|
|
|
promoteExprToType(rhsExpr, rhs);
|
|
|
|
} else if (result < 0) { // The right side is bigger, convert lhs.
|
|
|
|
lhs = Context.getFloatingTypeOfSizeWithinDomain(rhs, lhs);
|
|
|
|
if (!isCompAssign)
|
|
|
|
promoteExprToType(lhsExpr, lhs);
|
|
|
|
}
|
|
|
|
// At this point, lhs and rhs have the same rank/size. Now, make sure the
|
|
|
|
// domains match. This is a requirement for our implementation, C99
|
|
|
|
// does not require this promotion.
|
|
|
|
if (lhs != rhs) { // Domains don't match, we have complex/float mix.
|
|
|
|
if (lhs->isRealFloatingType()) { // handle "double, _Complex double".
|
2007-08-27 21:43:43 +00:00
|
|
|
if (!isCompAssign)
|
|
|
|
promoteExprToType(lhsExpr, rhs);
|
|
|
|
return rhs;
|
2007-08-27 21:32:55 +00:00
|
|
|
} else { // handle "_Complex double, double".
|
2007-08-27 21:43:43 +00:00
|
|
|
if (!isCompAssign)
|
|
|
|
promoteExprToType(rhsExpr, lhs);
|
|
|
|
return lhs;
|
2007-08-27 21:32:55 +00:00
|
|
|
}
|
2007-08-27 15:30:22 +00:00
|
|
|
}
|
2007-08-27 21:43:43 +00:00
|
|
|
return lhs; // The domain/size match exactly.
|
2007-04-25 01:22:31 +00:00
|
|
|
}
|
|
|
|
// Now handle "real" floating types (i.e. float, double, long double).
|
|
|
|
if (lhs->isRealFloatingType() || rhs->isRealFloatingType()) {
|
|
|
|
// if we have an integer operand, the result is the real floating type.
|
2007-07-17 00:58:39 +00:00
|
|
|
if (rhs->isIntegerType()) { // convert rhs to the lhs floating point type.
|
2007-08-24 19:07:16 +00:00
|
|
|
if (!isCompAssign) promoteExprToType(rhsExpr, lhs);
|
|
|
|
return lhs;
|
2007-07-17 00:58:39 +00:00
|
|
|
}
|
|
|
|
if (lhs->isIntegerType()) { // convert lhs to the rhs floating point type.
|
2007-08-24 19:07:16 +00:00
|
|
|
if (!isCompAssign) promoteExprToType(lhsExpr, rhs);
|
|
|
|
return rhs;
|
2007-07-17 00:58:39 +00:00
|
|
|
}
|
2007-07-15 02:02:06 +00:00
|
|
|
// We have two real floating types, float/complex combos were handled above.
|
|
|
|
// Convert the smaller operand to the bigger result.
|
2007-08-27 15:30:22 +00:00
|
|
|
int result = Context.compareFloatingType(lhs, rhs);
|
|
|
|
|
|
|
|
if (result > 0) { // convert the rhs
|
2007-08-24 19:07:16 +00:00
|
|
|
if (!isCompAssign) promoteExprToType(rhsExpr, lhs);
|
|
|
|
return lhs;
|
2007-07-17 00:58:39 +00:00
|
|
|
}
|
2007-08-27 15:30:22 +00:00
|
|
|
if (result < 0) { // convert the lhs
|
|
|
|
if (!isCompAssign) promoteExprToType(lhsExpr, rhs); // convert the lhs
|
|
|
|
return rhs;
|
|
|
|
}
|
|
|
|
assert(0 && "Sema::UsualArithmeticConversions(): illegal float comparison");
|
2007-04-24 20:56:26 +00:00
|
|
|
}
|
2007-07-15 02:02:06 +00:00
|
|
|
// Finally, we have two differing integer types.
|
2007-07-17 00:58:39 +00:00
|
|
|
if (Context.maxIntegerType(lhs, rhs) == lhs) { // convert the rhs
|
2007-08-24 19:07:16 +00:00
|
|
|
if (!isCompAssign) promoteExprToType(rhsExpr, lhs);
|
|
|
|
return lhs;
|
2007-07-17 00:58:39 +00:00
|
|
|
}
|
2007-08-24 19:07:16 +00:00
|
|
|
if (!isCompAssign) promoteExprToType(lhsExpr, rhs); // convert the lhs
|
|
|
|
return rhs;
|
2007-03-23 22:27:02 +00:00
|
|
|
}
|
|
|
|
|
2007-05-11 22:18:03 +00:00
|
|
|
// CheckPointerTypesForAssignment - This is a very tricky routine (despite
|
|
|
|
// being closely modeled after the C99 spec:-). The odd characteristic of this
|
|
|
|
// routine is it effectively iqnores the qualifiers on the top level pointee.
|
|
|
|
// This circumvents the usual type rules specified in 6.2.7p1 & 6.7.5.[1-3].
|
|
|
|
// FIXME: add a couple examples in this comment.
|
2007-06-06 18:38:38 +00:00
|
|
|
Sema::AssignmentCheckResult
|
|
|
|
Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) {
|
2007-05-11 22:18:03 +00:00
|
|
|
QualType lhptee, rhptee;
|
2007-05-11 04:00:31 +00:00
|
|
|
|
|
|
|
// get the "pointed to" type (ignoring qualifiers at the top level)
|
2007-07-31 21:27:01 +00:00
|
|
|
lhptee = lhsType->getAsPointerType()->getPointeeType();
|
|
|
|
rhptee = rhsType->getAsPointerType()->getPointeeType();
|
2007-05-11 04:00:31 +00:00
|
|
|
|
|
|
|
// make sure we operate on the canonical type
|
2007-05-11 22:18:03 +00:00
|
|
|
lhptee = lhptee.getCanonicalType();
|
|
|
|
rhptee = rhptee.getCanonicalType();
|
|
|
|
|
2007-06-06 18:38:38 +00:00
|
|
|
AssignmentCheckResult r = Compatible;
|
|
|
|
|
2007-05-11 22:18:03 +00:00
|
|
|
// C99 6.5.16.1p1: This following citation is common to constraints
|
|
|
|
// 3 & 4 (below). ...and the type *pointed to* by the left has all the
|
|
|
|
// qualifiers of the type *pointed to* by the right;
|
|
|
|
if ((lhptee.getQualifiers() & rhptee.getQualifiers()) !=
|
|
|
|
rhptee.getQualifiers())
|
|
|
|
r = CompatiblePointerDiscardsQualifiers;
|
|
|
|
|
|
|
|
// C99 6.5.16.1p1 (constraint 4): If one operand is a pointer to an object or
|
|
|
|
// incomplete type and the other is a pointer to a qualified or unqualified
|
|
|
|
// version of void...
|
|
|
|
if (lhptee.getUnqualifiedType()->isVoidType() &&
|
|
|
|
(rhptee->isObjectType() || rhptee->isIncompleteType()))
|
|
|
|
;
|
|
|
|
else if (rhptee.getUnqualifiedType()->isVoidType() &&
|
|
|
|
(lhptee->isObjectType() || lhptee->isIncompleteType()))
|
|
|
|
;
|
|
|
|
// C99 6.5.16.1p1 (constraint 3): both operands are pointers to qualified or
|
|
|
|
// unqualified versions of compatible types, ...
|
|
|
|
else if (!Type::typesAreCompatible(lhptee.getUnqualifiedType(),
|
|
|
|
rhptee.getUnqualifiedType()))
|
|
|
|
r = IncompatiblePointer; // this "trumps" PointerAssignDiscardsQualifiers
|
2007-06-06 18:38:38 +00:00
|
|
|
return r;
|
2007-05-11 04:00:31 +00:00
|
|
|
}
|
|
|
|
|
2007-06-06 18:38:38 +00:00
|
|
|
/// CheckAssignmentConstraints (C99 6.5.16) - This routine currently
|
2007-05-03 21:03:48 +00:00
|
|
|
/// has code to accommodate several GCC extensions when type checking
|
|
|
|
/// pointers. Here are some objectionable examples that GCC considers warnings:
|
|
|
|
///
|
|
|
|
/// int a, *pint;
|
|
|
|
/// short *pshort;
|
|
|
|
/// struct foo *pfoo;
|
|
|
|
///
|
|
|
|
/// pint = pshort; // warning: assignment from incompatible pointer type
|
|
|
|
/// a = pint; // warning: assignment makes integer from pointer without a cast
|
|
|
|
/// pint = a; // warning: assignment makes pointer from integer without a cast
|
|
|
|
/// pint = pfoo; // warning: assignment from incompatible pointer type
|
|
|
|
///
|
|
|
|
/// As a result, the code for dealing with pointers is more complex than the
|
|
|
|
/// C99 spec dictates.
|
|
|
|
/// Note: the warning above turn into errors when -pedantic-errors is enabled.
|
|
|
|
///
|
2007-06-06 18:38:38 +00:00
|
|
|
Sema::AssignmentCheckResult
|
|
|
|
Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
|
2007-07-24 21:46:40 +00:00
|
|
|
if (lhsType == rhsType) // common case, fast path...
|
|
|
|
return Compatible;
|
|
|
|
|
2007-10-12 23:56:29 +00:00
|
|
|
if (lhsType->isReferenceType() || rhsType->isReferenceType()) {
|
|
|
|
if (Type::referenceTypesAreCompatible(lhsType, rhsType))
|
|
|
|
return Compatible;
|
|
|
|
} else if (lhsType->isArithmeticType() && rhsType->isArithmeticType()) {
|
2007-07-10 22:20:04 +00:00
|
|
|
if (lhsType->isVectorType() || rhsType->isVectorType()) {
|
|
|
|
if (lhsType.getCanonicalType() != rhsType.getCanonicalType())
|
|
|
|
return Incompatible;
|
|
|
|
}
|
2007-06-06 18:38:38 +00:00
|
|
|
return Compatible;
|
2007-07-09 21:31:10 +00:00
|
|
|
} else if (lhsType->isPointerType()) {
|
2007-06-06 18:38:38 +00:00
|
|
|
if (rhsType->isIntegerType())
|
|
|
|
return PointerFromInt;
|
|
|
|
|
2007-05-11 22:18:03 +00:00
|
|
|
if (rhsType->isPointerType())
|
2007-06-06 18:38:38 +00:00
|
|
|
return CheckPointerTypesForAssignment(lhsType, rhsType);
|
2007-05-02 21:58:15 +00:00
|
|
|
} else if (rhsType->isPointerType()) {
|
2007-06-06 18:38:38 +00:00
|
|
|
// C99 6.5.16.1p1: the left operand is _Bool and the right is a pointer.
|
|
|
|
if ((lhsType->isIntegerType()) && (lhsType != Context.BoolTy))
|
|
|
|
return IntFromPointer;
|
|
|
|
|
2007-05-11 22:18:03 +00:00
|
|
|
if (lhsType->isPointerType())
|
2007-06-06 18:38:38 +00:00
|
|
|
return CheckPointerTypesForAssignment(lhsType, rhsType);
|
2007-05-11 04:00:31 +00:00
|
|
|
} else if (isa<TagType>(lhsType) && isa<TagType>(rhsType)) {
|
|
|
|
if (Type::tagTypesAreCompatible(lhsType, rhsType))
|
2007-06-06 18:38:38 +00:00
|
|
|
return Compatible;
|
2007-05-30 06:30:29 +00:00
|
|
|
}
|
2007-06-06 18:38:38 +00:00
|
|
|
return Incompatible;
|
2007-05-02 21:58:15 +00:00
|
|
|
}
|
|
|
|
|
2007-07-13 23:32:42 +00:00
|
|
|
Sema::AssignmentCheckResult
|
|
|
|
Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {
|
|
|
|
// This check seems unnatural, however it is necessary to insure the proper
|
|
|
|
// conversion of functions/arrays. If the conversion were done for all
|
2007-09-15 18:49:24 +00:00
|
|
|
// DeclExpr's (created by ActOnIdentifierExpr), it would mess up the unary
|
2007-07-13 23:32:42 +00:00
|
|
|
// expressions that surpress this implicit conversion (&, sizeof).
|
2007-07-16 21:54:35 +00:00
|
|
|
DefaultFunctionArrayConversion(rExpr);
|
2007-08-24 22:33:52 +00:00
|
|
|
|
|
|
|
Sema::AssignmentCheckResult result;
|
|
|
|
|
|
|
|
result = CheckAssignmentConstraints(lhsType, rExpr->getType());
|
2007-07-13 23:32:42 +00:00
|
|
|
|
2007-08-24 22:33:52 +00:00
|
|
|
// C99 6.5.16.1p2: The value of the right operand is converted to the
|
|
|
|
// type of the assignment expression.
|
|
|
|
if (rExpr->getType() != lhsType)
|
|
|
|
promoteExprToType(rExpr, lhsType);
|
|
|
|
return result;
|
2007-07-13 23:32:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Sema::AssignmentCheckResult
|
|
|
|
Sema::CheckCompoundAssignmentConstraints(QualType lhsType, QualType rhsType) {
|
|
|
|
return CheckAssignmentConstraints(lhsType, rhsType);
|
|
|
|
}
|
|
|
|
|
2007-07-13 16:58:59 +00:00
|
|
|
inline void Sema::InvalidOperands(SourceLocation loc, Expr *&lex, Expr *&rex) {
|
2007-05-29 14:23:36 +00:00
|
|
|
Diag(loc, diag::err_typecheck_invalid_operands,
|
|
|
|
lex->getType().getAsString(), rex->getType().getAsString(),
|
|
|
|
lex->getSourceRange(), rex->getSourceRange());
|
|
|
|
}
|
|
|
|
|
2007-07-13 16:58:59 +00:00
|
|
|
inline QualType Sema::CheckVectorOperands(SourceLocation loc, Expr *&lex,
|
|
|
|
Expr *&rex) {
|
2007-07-09 21:31:10 +00:00
|
|
|
QualType lhsType = lex->getType(), rhsType = rex->getType();
|
|
|
|
|
|
|
|
// make sure the vector types are identical.
|
|
|
|
if (lhsType == rhsType)
|
|
|
|
return lhsType;
|
|
|
|
// You cannot convert between vector values of different size.
|
|
|
|
Diag(loc, diag::err_typecheck_vector_not_convertable,
|
|
|
|
lex->getType().getAsString(), rex->getType().getAsString(),
|
|
|
|
lex->getSourceRange(), rex->getSourceRange());
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
inline QualType Sema::CheckMultiplyDivideOperands(
|
2007-08-24 19:07:16 +00:00
|
|
|
Expr *&lex, Expr *&rex, SourceLocation loc, bool isCompAssign)
|
2007-04-20 23:42:24 +00:00
|
|
|
{
|
2007-07-13 23:32:42 +00:00
|
|
|
QualType lhsType = lex->getType(), rhsType = rex->getType();
|
|
|
|
|
|
|
|
if (lhsType->isVectorType() || rhsType->isVectorType())
|
2007-07-09 21:31:10 +00:00
|
|
|
return CheckVectorOperands(loc, lex, rex);
|
2007-07-13 16:58:59 +00:00
|
|
|
|
2007-08-24 19:07:16 +00:00
|
|
|
QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
|
2007-04-20 23:42:24 +00:00
|
|
|
|
2007-07-17 00:58:39 +00:00
|
|
|
if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
|
2007-08-24 19:07:16 +00:00
|
|
|
return compType;
|
2007-05-29 14:23:36 +00:00
|
|
|
InvalidOperands(loc, lex, rex);
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
return QualType();
|
2007-03-30 23:47:58 +00:00
|
|
|
}
|
|
|
|
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
inline QualType Sema::CheckRemainderOperands(
|
2007-08-24 19:07:16 +00:00
|
|
|
Expr *&lex, Expr *&rex, SourceLocation loc, bool isCompAssign)
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
{
|
2007-07-13 23:32:42 +00:00
|
|
|
QualType lhsType = lex->getType(), rhsType = rex->getType();
|
|
|
|
|
2007-08-24 19:07:16 +00:00
|
|
|
QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
|
2007-07-17 00:58:39 +00:00
|
|
|
if (lex->getType()->isIntegerType() && rex->getType()->isIntegerType())
|
2007-08-24 19:07:16 +00:00
|
|
|
return compType;
|
2007-05-29 14:23:36 +00:00
|
|
|
InvalidOperands(loc, lex, rex);
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
|
|
|
inline QualType Sema::CheckAdditionOperands( // C99 6.5.6
|
2007-08-24 19:07:16 +00:00
|
|
|
Expr *&lex, Expr *&rex, SourceLocation loc, bool isCompAssign)
|
2007-04-24 00:23:05 +00:00
|
|
|
{
|
2007-07-16 22:23:01 +00:00
|
|
|
if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
|
2007-07-13 16:58:59 +00:00
|
|
|
return CheckVectorOperands(loc, lex, rex);
|
|
|
|
|
2007-08-24 19:07:16 +00:00
|
|
|
QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
|
2007-07-16 22:23:01 +00:00
|
|
|
|
2007-04-27 18:30:00 +00:00
|
|
|
// handle the common case first (both operands are arithmetic).
|
2007-07-17 00:58:39 +00:00
|
|
|
if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
|
2007-08-24 19:07:16 +00:00
|
|
|
return compType;
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
|
2007-07-17 00:58:39 +00:00
|
|
|
if (lex->getType()->isPointerType() && rex->getType()->isIntegerType())
|
|
|
|
return lex->getType();
|
|
|
|
if (lex->getType()->isIntegerType() && rex->getType()->isPointerType())
|
|
|
|
return rex->getType();
|
2007-05-29 14:23:36 +00:00
|
|
|
InvalidOperands(loc, lex, rex);
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
return QualType();
|
2007-03-21 21:08:52 +00:00
|
|
|
}
|
|
|
|
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
inline QualType Sema::CheckSubtractionOperands( // C99 6.5.6
|
2007-08-24 19:07:16 +00:00
|
|
|
Expr *&lex, Expr *&rex, SourceLocation loc, bool isCompAssign)
|
2007-04-24 00:23:05 +00:00
|
|
|
{
|
2007-07-16 22:23:01 +00:00
|
|
|
if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
|
2007-07-09 21:31:10 +00:00
|
|
|
return CheckVectorOperands(loc, lex, rex);
|
2007-07-13 23:32:42 +00:00
|
|
|
|
2007-08-24 19:07:16 +00:00
|
|
|
QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
|
2007-04-24 00:23:05 +00:00
|
|
|
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
// handle the common case first (both operands are arithmetic).
|
2007-07-17 00:58:39 +00:00
|
|
|
if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
|
2007-08-24 19:07:16 +00:00
|
|
|
return compType;
|
2007-07-16 22:23:01 +00:00
|
|
|
|
|
|
|
if (lex->getType()->isPointerType() && rex->getType()->isIntegerType())
|
2007-08-24 19:07:16 +00:00
|
|
|
return compType;
|
2007-07-16 22:23:01 +00:00
|
|
|
if (lex->getType()->isPointerType() && rex->getType()->isPointerType())
|
2007-07-13 03:05:23 +00:00
|
|
|
return Context.getPointerDiffType();
|
2007-05-29 14:23:36 +00:00
|
|
|
InvalidOperands(loc, lex, rex);
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
return QualType();
|
|
|
|
}
|
2007-04-24 00:23:05 +00:00
|
|
|
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
inline QualType Sema::CheckShiftOperands( // C99 6.5.7
|
2007-08-24 19:07:16 +00:00
|
|
|
Expr *&lex, Expr *&rex, SourceLocation loc, bool isCompAssign)
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
{
|
2007-06-05 20:52:21 +00:00
|
|
|
// FIXME: Shifts don't perform usual arithmetic conversions. This is wrong
|
|
|
|
// for int << longlong -> the result type should be int, not long long.
|
2007-08-24 19:07:16 +00:00
|
|
|
QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
|
2007-07-17 00:58:39 +00:00
|
|
|
// handle the common case first (both operands are arithmetic).
|
|
|
|
if (lex->getType()->isIntegerType() && rex->getType()->isIntegerType())
|
2007-08-24 19:07:16 +00:00
|
|
|
return compType;
|
2007-05-29 14:23:36 +00:00
|
|
|
InvalidOperands(loc, lex, rex);
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
return QualType();
|
2007-03-21 21:08:52 +00:00
|
|
|
}
|
|
|
|
|
2007-08-26 01:18:55 +00:00
|
|
|
inline QualType Sema::CheckCompareOperands( // C99 6.5.8
|
|
|
|
Expr *&lex, Expr *&rex, SourceLocation loc, bool isRelational)
|
2007-04-24 00:23:05 +00:00
|
|
|
{
|
2007-08-26 01:18:55 +00:00
|
|
|
// C99 6.5.8p3 / C99 6.5.9p4
|
2007-08-10 18:26:40 +00:00
|
|
|
if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
|
|
|
|
UsualArithmeticConversions(lex, rex);
|
|
|
|
else {
|
|
|
|
UsualUnaryConversions(lex);
|
|
|
|
UsualUnaryConversions(rex);
|
|
|
|
}
|
2007-07-16 21:54:35 +00:00
|
|
|
QualType lType = lex->getType();
|
|
|
|
QualType rType = rex->getType();
|
2007-04-24 00:23:05 +00:00
|
|
|
|
2007-08-26 01:18:55 +00:00
|
|
|
if (isRelational) {
|
|
|
|
if (lType->isRealType() && rType->isRealType())
|
|
|
|
return Context.IntTy;
|
|
|
|
} else {
|
2007-08-30 06:10:41 +00:00
|
|
|
if (lType->isFloatingType() && rType->isFloatingType())
|
2007-08-29 18:06:12 +00:00
|
|
|
Diag(loc, diag::warn_floatingpoint_eq);
|
|
|
|
|
2007-08-26 01:18:55 +00:00
|
|
|
if (lType->isArithmeticType() && rType->isArithmeticType())
|
|
|
|
return Context.IntTy;
|
|
|
|
}
|
2007-04-27 18:30:00 +00:00
|
|
|
|
2007-08-26 01:10:14 +00:00
|
|
|
bool LHSIsNull = lex->isNullPointerConstant(Context);
|
|
|
|
bool RHSIsNull = rex->isNullPointerConstant(Context);
|
|
|
|
|
2007-08-26 01:18:55 +00:00
|
|
|
// All of the following pointer related warnings are GCC extensions, except
|
|
|
|
// when handling null pointer constants. One day, we can consider making them
|
|
|
|
// errors (when -pedantic-errors is enabled).
|
2007-08-27 04:08:11 +00:00
|
|
|
if (lType->isPointerType() && rType->isPointerType()) { // C99 6.5.8p2
|
2007-08-26 01:10:14 +00:00
|
|
|
if (!LHSIsNull && !RHSIsNull &&
|
2007-08-27 04:08:11 +00:00
|
|
|
!Type::pointerTypesAreCompatible(lType.getUnqualifiedType(),
|
|
|
|
rType.getUnqualifiedType())) {
|
2007-08-16 21:48:38 +00:00
|
|
|
Diag(loc, diag::ext_typecheck_comparison_of_distinct_pointers,
|
|
|
|
lType.getAsString(), rType.getAsString(),
|
|
|
|
lex->getSourceRange(), rex->getSourceRange());
|
2007-06-13 21:41:08 +00:00
|
|
|
}
|
2007-08-26 01:10:14 +00:00
|
|
|
promoteExprToType(rex, lType); // promote the pointer to pointer
|
2007-08-16 21:48:38 +00:00
|
|
|
return Context.IntTy;
|
|
|
|
}
|
|
|
|
if (lType->isPointerType() && rType->isIntegerType()) {
|
2007-08-26 01:10:14 +00:00
|
|
|
if (!RHSIsNull)
|
2007-08-16 21:48:38 +00:00
|
|
|
Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer,
|
|
|
|
lType.getAsString(), rType.getAsString(),
|
|
|
|
lex->getSourceRange(), rex->getSourceRange());
|
2007-08-26 01:10:14 +00:00
|
|
|
promoteExprToType(rex, lType); // promote the integer to pointer
|
2007-08-16 21:48:38 +00:00
|
|
|
return Context.IntTy;
|
|
|
|
}
|
|
|
|
if (lType->isIntegerType() && rType->isPointerType()) {
|
2007-08-26 01:10:14 +00:00
|
|
|
if (!LHSIsNull)
|
2007-08-16 21:48:38 +00:00
|
|
|
Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer,
|
|
|
|
lType.getAsString(), rType.getAsString(),
|
|
|
|
lex->getSourceRange(), rex->getSourceRange());
|
2007-08-26 01:10:14 +00:00
|
|
|
promoteExprToType(lex, rType); // promote the integer to pointer
|
2007-08-16 21:48:38 +00:00
|
|
|
return Context.IntTy;
|
2007-05-15 02:32:35 +00:00
|
|
|
}
|
2007-05-29 14:23:36 +00:00
|
|
|
InvalidOperands(loc, lex, rex);
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
return QualType();
|
2007-03-21 21:08:52 +00:00
|
|
|
}
|
|
|
|
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
inline QualType Sema::CheckBitwiseOperands(
|
2007-08-24 19:07:16 +00:00
|
|
|
Expr *&lex, Expr *&rex, SourceLocation loc, bool isCompAssign)
|
2007-04-24 00:23:05 +00:00
|
|
|
{
|
2007-07-16 22:23:01 +00:00
|
|
|
if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
|
2007-07-09 21:31:10 +00:00
|
|
|
return CheckVectorOperands(loc, lex, rex);
|
2007-07-13 23:32:42 +00:00
|
|
|
|
2007-08-24 19:07:16 +00:00
|
|
|
QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
|
2007-04-24 00:23:05 +00:00
|
|
|
|
2007-07-17 00:58:39 +00:00
|
|
|
if (lex->getType()->isIntegerType() && rex->getType()->isIntegerType())
|
2007-08-24 19:07:16 +00:00
|
|
|
return compType;
|
2007-05-29 14:23:36 +00:00
|
|
|
InvalidOperands(loc, lex, rex);
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
return QualType();
|
2007-03-21 21:08:52 +00:00
|
|
|
}
|
|
|
|
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]
|
2007-07-13 16:58:59 +00:00
|
|
|
Expr *&lex, Expr *&rex, SourceLocation loc)
|
2007-04-24 00:23:05 +00:00
|
|
|
{
|
2007-07-16 21:54:35 +00:00
|
|
|
UsualUnaryConversions(lex);
|
|
|
|
UsualUnaryConversions(rex);
|
2007-04-27 18:30:00 +00:00
|
|
|
|
2007-07-17 00:58:39 +00:00
|
|
|
if (lex->getType()->isScalarType() || rex->getType()->isScalarType())
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
return Context.IntTy;
|
2007-05-29 14:23:36 +00:00
|
|
|
InvalidOperands(loc, lex, rex);
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
return QualType();
|
2007-04-26 20:39:23 +00:00
|
|
|
}
|
|
|
|
|
2007-05-07 00:24:15 +00:00
|
|
|
inline QualType Sema::CheckAssignmentOperands( // C99 6.5.16.1
|
2007-08-24 22:33:52 +00:00
|
|
|
Expr *lex, Expr *&rex, SourceLocation loc, QualType compoundType)
|
2007-04-26 20:39:23 +00:00
|
|
|
{
|
2007-04-27 21:51:21 +00:00
|
|
|
QualType lhsType = lex->getType();
|
2007-05-07 00:24:15 +00:00
|
|
|
QualType rhsType = compoundType.isNull() ? rex->getType() : compoundType;
|
2007-05-11 04:00:31 +00:00
|
|
|
bool hadError = false;
|
2007-05-27 23:58:33 +00:00
|
|
|
Expr::isModifiableLvalueResult mlval = lex->isModifiableLvalue();
|
|
|
|
|
|
|
|
switch (mlval) { // C99 6.5.16p2
|
|
|
|
case Expr::MLV_Valid:
|
|
|
|
break;
|
|
|
|
case Expr::MLV_ConstQualified:
|
|
|
|
Diag(loc, diag::err_typecheck_assign_const, lex->getSourceRange());
|
|
|
|
hadError = true;
|
|
|
|
break;
|
|
|
|
case Expr::MLV_ArrayType:
|
|
|
|
Diag(loc, diag::err_typecheck_array_not_modifiable_lvalue,
|
|
|
|
lhsType.getAsString(), lex->getSourceRange());
|
|
|
|
return QualType();
|
|
|
|
case Expr::MLV_NotObjectType:
|
|
|
|
Diag(loc, diag::err_typecheck_non_object_not_modifiable_lvalue,
|
|
|
|
lhsType.getAsString(), lex->getSourceRange());
|
|
|
|
return QualType();
|
|
|
|
case Expr::MLV_InvalidExpression:
|
|
|
|
Diag(loc, diag::err_typecheck_expression_not_modifiable_lvalue,
|
|
|
|
lex->getSourceRange());
|
|
|
|
return QualType();
|
|
|
|
case Expr::MLV_IncompleteType:
|
|
|
|
case Expr::MLV_IncompleteVoidType:
|
|
|
|
Diag(loc, diag::err_typecheck_incomplete_type_not_modifiable_lvalue,
|
|
|
|
lhsType.getAsString(), lex->getSourceRange());
|
|
|
|
return QualType();
|
2007-07-30 03:29:09 +00:00
|
|
|
case Expr::MLV_DuplicateVectorComponents:
|
|
|
|
Diag(loc, diag::err_typecheck_duplicate_vector_components_not_mlvalue,
|
|
|
|
lex->getSourceRange());
|
|
|
|
return QualType();
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
}
|
2007-07-13 23:32:42 +00:00
|
|
|
AssignmentCheckResult result;
|
|
|
|
|
|
|
|
if (compoundType.isNull())
|
|
|
|
result = CheckSingleAssignmentConstraints(lhsType, rex);
|
|
|
|
else
|
|
|
|
result = CheckCompoundAssignmentConstraints(lhsType, rhsType);
|
2007-07-31 12:34:36 +00:00
|
|
|
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
// decode the result (notice that extensions still return a type).
|
|
|
|
switch (result) {
|
|
|
|
case Compatible:
|
2007-05-11 04:00:31 +00:00
|
|
|
break;
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
case Incompatible:
|
2007-05-18 01:06:45 +00:00
|
|
|
Diag(loc, diag::err_typecheck_assign_incompatible,
|
2007-05-19 07:03:17 +00:00
|
|
|
lhsType.getAsString(), rhsType.getAsString(),
|
|
|
|
lex->getSourceRange(), rex->getSourceRange());
|
2007-05-11 04:00:31 +00:00
|
|
|
hadError = true;
|
|
|
|
break;
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
case PointerFromInt:
|
|
|
|
// check for null pointer constant (C99 6.3.2.3p3)
|
2007-07-15 23:26:56 +00:00
|
|
|
if (compoundType.isNull() && !rex->isNullPointerConstant(Context)) {
|
2007-05-30 04:20:12 +00:00
|
|
|
Diag(loc, diag::ext_typecheck_assign_pointer_int,
|
|
|
|
lhsType.getAsString(), rhsType.getAsString(),
|
2007-05-27 23:58:33 +00:00
|
|
|
lex->getSourceRange(), rex->getSourceRange());
|
2007-05-30 16:27:15 +00:00
|
|
|
}
|
2007-05-11 04:00:31 +00:00
|
|
|
break;
|
2007-05-30 04:20:12 +00:00
|
|
|
case IntFromPointer:
|
|
|
|
Diag(loc, diag::ext_typecheck_assign_pointer_int,
|
|
|
|
lhsType.getAsString(), rhsType.getAsString(),
|
2007-05-27 23:58:33 +00:00
|
|
|
lex->getSourceRange(), rex->getSourceRange());
|
2007-05-11 04:00:31 +00:00
|
|
|
break;
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
case IncompatiblePointer:
|
2007-05-27 23:58:33 +00:00
|
|
|
Diag(loc, diag::ext_typecheck_assign_incompatible_pointer,
|
|
|
|
lhsType.getAsString(), rhsType.getAsString(),
|
|
|
|
lex->getSourceRange(), rex->getSourceRange());
|
2007-05-11 04:00:31 +00:00
|
|
|
break;
|
|
|
|
case CompatiblePointerDiscardsQualifiers:
|
2007-05-27 23:58:33 +00:00
|
|
|
Diag(loc, diag::ext_typecheck_assign_discards_qualifiers,
|
|
|
|
lhsType.getAsString(), rhsType.getAsString(),
|
|
|
|
lex->getSourceRange(), rex->getSourceRange());
|
2007-05-11 04:00:31 +00:00
|
|
|
break;
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
}
|
2007-06-06 18:38:38 +00:00
|
|
|
// C99 6.5.16p3: The type of an assignment expression is the type of the
|
|
|
|
// left operand unless the left operand has qualified type, in which case
|
|
|
|
// it is the unqualified version of the type of the left operand.
|
|
|
|
// C99 6.5.16.1p2: In simple assignment, the value of the right operand
|
|
|
|
// is converted to the type of the assignment expression (above).
|
2007-08-30 17:45:32 +00:00
|
|
|
// C++ 5.17p1: the type of the assignment expression is that of its left
|
|
|
|
// oprdu.
|
2007-06-06 18:38:38 +00:00
|
|
|
return hadError ? QualType() : lhsType.getUnqualifiedType();
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
inline QualType Sema::CheckCommaOperands( // C99 6.5.17
|
2007-07-13 16:58:59 +00:00
|
|
|
Expr *&lex, Expr *&rex, SourceLocation loc) {
|
2007-07-16 21:54:35 +00:00
|
|
|
UsualUnaryConversions(rex);
|
|
|
|
return rex->getType();
|
2007-03-21 21:08:52 +00:00
|
|
|
}
|
|
|
|
|
2007-07-13 16:58:59 +00:00
|
|
|
/// CheckIncrementDecrementOperand - unlike most "Check" methods, this routine
|
|
|
|
/// doesn't need to call UsualUnaryConversions or UsualArithmeticConversions.
|
2007-05-18 22:53:50 +00:00
|
|
|
QualType Sema::CheckIncrementDecrementOperand(Expr *op, SourceLocation OpLoc) {
|
2007-07-13 16:58:59 +00:00
|
|
|
QualType resType = op->getType();
|
2007-05-07 00:24:15 +00:00
|
|
|
assert(!resType.isNull() && "no type for increment/decrement expression");
|
2007-04-05 21:15:20 +00:00
|
|
|
|
2007-08-24 17:20:07 +00:00
|
|
|
// C99 6.5.2.4p1: We allow complex as a GCC extension.
|
2007-05-07 00:24:15 +00:00
|
|
|
if (const PointerType *pt = dyn_cast<PointerType>(resType)) {
|
|
|
|
if (!pt->getPointeeType()->isObjectType()) { // C99 6.5.2.4p2, 6.5.6p2
|
2007-05-18 22:53:50 +00:00
|
|
|
Diag(OpLoc, diag::err_typecheck_arithmetic_incomplete_type,
|
|
|
|
resType.getAsString(), op->getSourceRange());
|
2007-05-07 00:24:15 +00:00
|
|
|
return QualType();
|
|
|
|
}
|
2007-08-24 17:20:07 +00:00
|
|
|
} else if (!resType->isRealType()) {
|
|
|
|
if (resType->isComplexType())
|
|
|
|
// C99 does not support ++/-- on complex types.
|
|
|
|
Diag(OpLoc, diag::ext_integer_increment_complex,
|
|
|
|
resType.getAsString(), op->getSourceRange());
|
|
|
|
else {
|
|
|
|
Diag(OpLoc, diag::err_typecheck_illegal_increment_decrement,
|
|
|
|
resType.getAsString(), op->getSourceRange());
|
|
|
|
return QualType();
|
|
|
|
}
|
2007-04-03 23:13:13 +00:00
|
|
|
}
|
2007-08-23 21:37:33 +00:00
|
|
|
// At this point, we know we have a real, complex or pointer type.
|
|
|
|
// Now make sure the operand is a modifiable lvalue.
|
2007-05-27 23:58:33 +00:00
|
|
|
Expr::isModifiableLvalueResult mlval = op->isModifiableLvalue();
|
|
|
|
if (mlval != Expr::MLV_Valid) {
|
|
|
|
// FIXME: emit a more precise diagnostic...
|
2007-05-18 22:53:50 +00:00
|
|
|
Diag(OpLoc, diag::err_typecheck_invalid_lvalue_incr_decr,
|
2007-05-19 07:03:17 +00:00
|
|
|
op->getSourceRange());
|
2007-05-07 00:24:15 +00:00
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
return resType;
|
2007-03-21 21:08:52 +00:00
|
|
|
}
|
|
|
|
|
2007-04-24 00:23:05 +00:00
|
|
|
/// getPrimaryDeclaration - Helper function for CheckAddressOfOperand().
|
2007-04-19 23:00:49 +00:00
|
|
|
/// 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].
|
2007-04-24 00:23:05 +00:00
|
|
|
static Decl *getPrimaryDeclaration(Expr *e) {
|
2007-04-19 23:00:49 +00:00
|
|
|
switch (e->getStmtClass()) {
|
|
|
|
case Stmt::DeclRefExprClass:
|
|
|
|
return cast<DeclRefExpr>(e)->getDecl();
|
|
|
|
case Stmt::MemberExprClass:
|
2007-04-24 00:23:05 +00:00
|
|
|
return getPrimaryDeclaration(cast<MemberExpr>(e)->getBase());
|
2007-04-19 23:00:49 +00:00
|
|
|
case Stmt::ArraySubscriptExprClass:
|
2007-04-24 00:23:05 +00:00
|
|
|
return getPrimaryDeclaration(cast<ArraySubscriptExpr>(e)->getBase());
|
2007-04-19 23:00:49 +00:00
|
|
|
case Stmt::CallExprClass:
|
2007-04-24 00:23:05 +00:00
|
|
|
return getPrimaryDeclaration(cast<CallExpr>(e)->getCallee());
|
2007-04-19 23:00:49 +00:00
|
|
|
case Stmt::UnaryOperatorClass:
|
2007-04-24 00:23:05 +00:00
|
|
|
return getPrimaryDeclaration(cast<UnaryOperator>(e)->getSubExpr());
|
2007-04-19 23:00:49 +00:00
|
|
|
case Stmt::ParenExprClass:
|
2007-04-24 00:23:05 +00:00
|
|
|
return getPrimaryDeclaration(cast<ParenExpr>(e)->getSubExpr());
|
2007-04-19 23:00:49 +00:00
|
|
|
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 &
|
2007-05-16 19:47:19 +00:00
|
|
|
/// operator (C99 6.3.2.1p[2-4]), and its result is never an lvalue.
|
2007-05-07 00:24:15 +00:00
|
|
|
QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) {
|
2007-04-24 00:23:05 +00:00
|
|
|
Decl *dcl = getPrimaryDeclaration(op);
|
2007-05-27 23:58:33 +00:00
|
|
|
Expr::isLvalueResult lval = op->isLvalue();
|
2007-04-19 23:00:49 +00:00
|
|
|
|
2007-05-27 23:58:33 +00:00
|
|
|
if (lval != Expr::LV_Valid) { // C99 6.5.3.2p1
|
2007-05-14 18:14:51 +00:00
|
|
|
if (dcl && isa<FunctionDecl>(dcl)) // allow function designators
|
|
|
|
;
|
2007-05-27 23:58:33 +00:00
|
|
|
else { // FIXME: emit more specific diag...
|
2007-05-18 22:53:50 +00:00
|
|
|
Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof,
|
|
|
|
op->getSourceRange());
|
2007-05-07 00:24:15 +00:00
|
|
|
return QualType();
|
|
|
|
}
|
2007-04-19 23:00:49 +00:00
|
|
|
} 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)) {
|
2007-05-07 00:24:15 +00:00
|
|
|
if (vd->getStorageClass() == VarDecl::Register) {
|
2007-05-18 22:53:50 +00:00
|
|
|
Diag(OpLoc, diag::err_typecheck_address_of_register,
|
2007-05-19 07:03:17 +00:00
|
|
|
op->getSourceRange());
|
2007-05-07 00:24:15 +00:00
|
|
|
return QualType();
|
|
|
|
}
|
2007-04-25 19:01:39 +00:00
|
|
|
} else
|
|
|
|
assert(0 && "Unknown/unexpected decl type");
|
|
|
|
|
2007-04-19 23:00:49 +00:00
|
|
|
// FIXME: add check for bitfields!
|
|
|
|
}
|
|
|
|
// If the operand has type "type", the result has type "pointer to type".
|
2007-05-07 00:24:15 +00:00
|
|
|
return Context.getPointerType(op->getType());
|
2007-04-19 23:00:49 +00:00
|
|
|
}
|
|
|
|
|
2007-05-07 00:24:15 +00:00
|
|
|
QualType Sema::CheckIndirectionOperand(Expr *op, SourceLocation OpLoc) {
|
2007-07-16 21:54:35 +00:00
|
|
|
UsualUnaryConversions(op);
|
|
|
|
QualType qType = op->getType();
|
2007-04-19 23:00:49 +00:00
|
|
|
|
2007-07-31 16:53:04 +00:00
|
|
|
if (const PointerType *PT = qType->getAsPointerType()) {
|
2007-05-28 16:15:57 +00:00
|
|
|
QualType ptype = PT->getPointeeType();
|
|
|
|
// C99 6.5.3.2p4. "if it points to an object,...".
|
|
|
|
if (ptype->isIncompleteType()) { // An incomplete type is not an object
|
|
|
|
// GCC compat: special case 'void *' (treat as warning).
|
|
|
|
if (ptype->isVoidType()) {
|
|
|
|
Diag(OpLoc, diag::ext_typecheck_deref_ptr_to_void,
|
2007-05-30 00:06:37 +00:00
|
|
|
qType.getAsString(), op->getSourceRange());
|
2007-05-28 16:15:57 +00:00
|
|
|
} else {
|
|
|
|
Diag(OpLoc, diag::err_typecheck_deref_incomplete_type,
|
2007-05-30 00:06:37 +00:00
|
|
|
ptype.getAsString(), op->getSourceRange());
|
2007-05-28 16:15:57 +00:00
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ptype;
|
|
|
|
}
|
|
|
|
Diag(OpLoc, diag::err_typecheck_indirection_requires_pointer,
|
2007-05-30 00:06:37 +00:00
|
|
|
qType.getAsString(), op->getSourceRange());
|
2007-05-07 00:24:15 +00:00
|
|
|
return QualType();
|
2007-04-24 00:23:05 +00:00
|
|
|
}
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
|
|
|
|
static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode(
|
|
|
|
tok::TokenKind Kind) {
|
|
|
|
BinaryOperator::Opcode Opc;
|
|
|
|
switch (Kind) {
|
|
|
|
default: assert(0 && "Unknown binop!");
|
|
|
|
case tok::star: Opc = BinaryOperator::Mul; break;
|
|
|
|
case tok::slash: Opc = BinaryOperator::Div; break;
|
|
|
|
case tok::percent: Opc = BinaryOperator::Rem; break;
|
|
|
|
case tok::plus: Opc = BinaryOperator::Add; break;
|
|
|
|
case tok::minus: Opc = BinaryOperator::Sub; break;
|
|
|
|
case tok::lessless: Opc = BinaryOperator::Shl; break;
|
|
|
|
case tok::greatergreater: Opc = BinaryOperator::Shr; break;
|
|
|
|
case tok::lessequal: Opc = BinaryOperator::LE; break;
|
|
|
|
case tok::less: Opc = BinaryOperator::LT; break;
|
|
|
|
case tok::greaterequal: Opc = BinaryOperator::GE; break;
|
|
|
|
case tok::greater: Opc = BinaryOperator::GT; break;
|
|
|
|
case tok::exclaimequal: Opc = BinaryOperator::NE; break;
|
|
|
|
case tok::equalequal: Opc = BinaryOperator::EQ; break;
|
|
|
|
case tok::amp: Opc = BinaryOperator::And; break;
|
|
|
|
case tok::caret: Opc = BinaryOperator::Xor; break;
|
|
|
|
case tok::pipe: Opc = BinaryOperator::Or; break;
|
|
|
|
case tok::ampamp: Opc = BinaryOperator::LAnd; break;
|
|
|
|
case tok::pipepipe: Opc = BinaryOperator::LOr; break;
|
|
|
|
case tok::equal: Opc = BinaryOperator::Assign; break;
|
|
|
|
case tok::starequal: Opc = BinaryOperator::MulAssign; break;
|
|
|
|
case tok::slashequal: Opc = BinaryOperator::DivAssign; break;
|
|
|
|
case tok::percentequal: Opc = BinaryOperator::RemAssign; break;
|
|
|
|
case tok::plusequal: Opc = BinaryOperator::AddAssign; break;
|
|
|
|
case tok::minusequal: Opc = BinaryOperator::SubAssign; break;
|
|
|
|
case tok::lesslessequal: Opc = BinaryOperator::ShlAssign; break;
|
|
|
|
case tok::greatergreaterequal: Opc = BinaryOperator::ShrAssign; break;
|
|
|
|
case tok::ampequal: Opc = BinaryOperator::AndAssign; break;
|
|
|
|
case tok::caretequal: Opc = BinaryOperator::XorAssign; break;
|
|
|
|
case tok::pipeequal: Opc = BinaryOperator::OrAssign; break;
|
|
|
|
case tok::comma: Opc = BinaryOperator::Comma; break;
|
|
|
|
}
|
|
|
|
return Opc;
|
|
|
|
}
|
|
|
|
|
2007-05-07 00:24:15 +00:00
|
|
|
static inline UnaryOperator::Opcode ConvertTokenKindToUnaryOpcode(
|
|
|
|
tok::TokenKind Kind) {
|
|
|
|
UnaryOperator::Opcode Opc;
|
|
|
|
switch (Kind) {
|
|
|
|
default: assert(0 && "Unknown unary op!");
|
|
|
|
case tok::plusplus: Opc = UnaryOperator::PreInc; break;
|
|
|
|
case tok::minusminus: Opc = UnaryOperator::PreDec; break;
|
|
|
|
case tok::amp: Opc = UnaryOperator::AddrOf; break;
|
|
|
|
case tok::star: Opc = UnaryOperator::Deref; break;
|
|
|
|
case tok::plus: Opc = UnaryOperator::Plus; break;
|
|
|
|
case tok::minus: Opc = UnaryOperator::Minus; break;
|
|
|
|
case tok::tilde: Opc = UnaryOperator::Not; break;
|
|
|
|
case tok::exclaim: Opc = UnaryOperator::LNot; break;
|
|
|
|
case tok::kw_sizeof: Opc = UnaryOperator::SizeOf; break;
|
|
|
|
case tok::kw___alignof: Opc = UnaryOperator::AlignOf; break;
|
|
|
|
case tok::kw___real: Opc = UnaryOperator::Real; break;
|
|
|
|
case tok::kw___imag: Opc = UnaryOperator::Imag; break;
|
2007-06-08 22:16:53 +00:00
|
|
|
case tok::kw___extension__: Opc = UnaryOperator::Extension; break;
|
2007-05-07 00:24:15 +00:00
|
|
|
}
|
|
|
|
return Opc;
|
|
|
|
}
|
|
|
|
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
// Binary Operators. 'Tok' is the token for the operator.
|
2007-09-16 03:34:24 +00:00
|
|
|
Action::ExprResult Sema::ActOnBinOp(SourceLocation TokLoc, tok::TokenKind Kind,
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
ExprTy *LHS, ExprTy *RHS) {
|
|
|
|
BinaryOperator::Opcode Opc = ConvertTokenKindToBinaryOpcode(Kind);
|
|
|
|
Expr *lhs = (Expr *)LHS, *rhs = (Expr*)RHS;
|
|
|
|
|
2007-09-16 03:34:24 +00:00
|
|
|
assert((lhs != 0) && "ActOnBinOp(): missing left expression");
|
|
|
|
assert((rhs != 0) && "ActOnBinOp(): missing right expression");
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
|
2007-06-28 03:53:10 +00:00
|
|
|
QualType ResultTy; // Result type of the binary operator.
|
|
|
|
QualType CompTy; // Computation type for compound assignments (e.g. '+=')
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
|
|
|
|
switch (Opc) {
|
|
|
|
default:
|
|
|
|
assert(0 && "Unknown binary expr!");
|
|
|
|
case BinaryOperator::Assign:
|
2007-06-28 03:53:10 +00:00
|
|
|
ResultTy = CheckAssignmentOperands(lhs, rhs, TokLoc, QualType());
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
break;
|
|
|
|
case BinaryOperator::Mul:
|
|
|
|
case BinaryOperator::Div:
|
2007-06-28 03:53:10 +00:00
|
|
|
ResultTy = CheckMultiplyDivideOperands(lhs, rhs, TokLoc);
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
break;
|
|
|
|
case BinaryOperator::Rem:
|
2007-06-28 03:53:10 +00:00
|
|
|
ResultTy = CheckRemainderOperands(lhs, rhs, TokLoc);
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
break;
|
|
|
|
case BinaryOperator::Add:
|
2007-06-28 03:53:10 +00:00
|
|
|
ResultTy = CheckAdditionOperands(lhs, rhs, TokLoc);
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
break;
|
|
|
|
case BinaryOperator::Sub:
|
2007-06-28 03:53:10 +00:00
|
|
|
ResultTy = CheckSubtractionOperands(lhs, rhs, TokLoc);
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
break;
|
|
|
|
case BinaryOperator::Shl:
|
|
|
|
case BinaryOperator::Shr:
|
2007-06-28 03:53:10 +00:00
|
|
|
ResultTy = CheckShiftOperands(lhs, rhs, TokLoc);
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
break;
|
|
|
|
case BinaryOperator::LE:
|
|
|
|
case BinaryOperator::LT:
|
|
|
|
case BinaryOperator::GE:
|
|
|
|
case BinaryOperator::GT:
|
2007-08-26 01:18:55 +00:00
|
|
|
ResultTy = CheckCompareOperands(lhs, rhs, TokLoc, true);
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
break;
|
|
|
|
case BinaryOperator::EQ:
|
|
|
|
case BinaryOperator::NE:
|
2007-08-26 01:18:55 +00:00
|
|
|
ResultTy = CheckCompareOperands(lhs, rhs, TokLoc, false);
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
break;
|
|
|
|
case BinaryOperator::And:
|
|
|
|
case BinaryOperator::Xor:
|
|
|
|
case BinaryOperator::Or:
|
2007-06-28 03:53:10 +00:00
|
|
|
ResultTy = CheckBitwiseOperands(lhs, rhs, TokLoc);
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
break;
|
|
|
|
case BinaryOperator::LAnd:
|
|
|
|
case BinaryOperator::LOr:
|
2007-06-28 03:53:10 +00:00
|
|
|
ResultTy = CheckLogicalOperands(lhs, rhs, TokLoc);
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
break;
|
|
|
|
case BinaryOperator::MulAssign:
|
|
|
|
case BinaryOperator::DivAssign:
|
2007-08-24 19:07:16 +00:00
|
|
|
CompTy = CheckMultiplyDivideOperands(lhs, rhs, TokLoc, true);
|
2007-06-28 03:53:10 +00:00
|
|
|
if (!CompTy.isNull())
|
|
|
|
ResultTy = CheckAssignmentOperands(lhs, rhs, TokLoc, CompTy);
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
break;
|
|
|
|
case BinaryOperator::RemAssign:
|
2007-08-24 19:07:16 +00:00
|
|
|
CompTy = CheckRemainderOperands(lhs, rhs, TokLoc, true);
|
2007-06-28 03:53:10 +00:00
|
|
|
if (!CompTy.isNull())
|
|
|
|
ResultTy = CheckAssignmentOperands(lhs, rhs, TokLoc, CompTy);
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
break;
|
|
|
|
case BinaryOperator::AddAssign:
|
2007-08-24 19:07:16 +00:00
|
|
|
CompTy = CheckAdditionOperands(lhs, rhs, TokLoc, true);
|
2007-06-28 03:53:10 +00:00
|
|
|
if (!CompTy.isNull())
|
|
|
|
ResultTy = CheckAssignmentOperands(lhs, rhs, TokLoc, CompTy);
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
break;
|
|
|
|
case BinaryOperator::SubAssign:
|
2007-08-24 19:07:16 +00:00
|
|
|
CompTy = CheckSubtractionOperands(lhs, rhs, TokLoc, true);
|
2007-06-28 03:53:10 +00:00
|
|
|
if (!CompTy.isNull())
|
|
|
|
ResultTy = CheckAssignmentOperands(lhs, rhs, TokLoc, CompTy);
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
break;
|
|
|
|
case BinaryOperator::ShlAssign:
|
|
|
|
case BinaryOperator::ShrAssign:
|
2007-08-24 19:07:16 +00:00
|
|
|
CompTy = CheckShiftOperands(lhs, rhs, TokLoc, true);
|
2007-06-28 03:53:10 +00:00
|
|
|
if (!CompTy.isNull())
|
|
|
|
ResultTy = CheckAssignmentOperands(lhs, rhs, TokLoc, CompTy);
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
break;
|
|
|
|
case BinaryOperator::AndAssign:
|
|
|
|
case BinaryOperator::XorAssign:
|
|
|
|
case BinaryOperator::OrAssign:
|
2007-08-24 19:07:16 +00:00
|
|
|
CompTy = CheckBitwiseOperands(lhs, rhs, TokLoc, true);
|
2007-06-28 03:53:10 +00:00
|
|
|
if (!CompTy.isNull())
|
|
|
|
ResultTy = CheckAssignmentOperands(lhs, rhs, TokLoc, CompTy);
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
break;
|
|
|
|
case BinaryOperator::Comma:
|
2007-06-28 03:53:10 +00:00
|
|
|
ResultTy = CheckCommaOperands(lhs, rhs, TokLoc);
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
break;
|
|
|
|
}
|
2007-06-28 03:53:10 +00:00
|
|
|
if (ResultTy.isNull())
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
return true;
|
2007-06-28 03:53:10 +00:00
|
|
|
if (CompTy.isNull())
|
2007-08-28 18:36:55 +00:00
|
|
|
return new BinaryOperator(lhs, rhs, Opc, ResultTy, TokLoc);
|
2007-06-28 03:53:10 +00:00
|
|
|
else
|
2007-08-28 18:36:55 +00:00
|
|
|
return new CompoundAssignOperator(lhs, rhs, Opc, ResultTy, CompTy, TokLoc);
|
Bug #:
Submitted by:
Reviewed by:
Implemented type checking for compound assignments (*=, /=, etc.).
This encouraged me to do a fairly dramatic refactoring of the Check* functions.
(since I wanted to reuse the existing work, rather than duplicate the logic).
For example, I changed all the Check* functions to return a QualType (instead
of returning an Expr). This had a very nice side benefit...there is now
only one instantiation point for BinaryOperator()! (A property I've always
wanted...separating type checking from AST building is *much* nicer). Another
change is to remove "code" from all the Check* functions (this allowed
me to remove the weird comment about enums/unsigned:-). Removing the
code forced me to add a few functions, however. For example,
< ExprResult CheckAdditiveOperands( // C99 6.5.6
< Expr *lex, Expr *rex, SourceLocation OpLoc, unsigned OpCode);
> inline QualType CheckAdditionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
> inline QualType CheckSubtractionOperands( // C99 6.5.6
> Expr *lex, Expr *rex, SourceLocation OpLoc);
While this isn't as terse, it more closely reflects the differences in
the typechecking logic. For example, I disliked having to check the code again
in CheckMultiplicativeOperands/CheckAdditiveOperands.
Created the following helper functions:
- Expr::isNullPointerConstant().
- SemaExpr.cpp: static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode().
This was purely asethetic, since ParseBinOp() is now larger. I didn't feel
like looking at 2 huge switch statements. ParseBinOp() now avoids using
any of the BinaryOperator predicates (since I switched to a switch statement:-)
Only one regret (minor). I couldn't figure out how to avoid having two assign functions,
CheckCompoundAssignmentOperands, CheckSimpleAssignmentOperands. Conceptually,
the two functions make sense. Unfortunately, their implementation contains a lot of
duplication (thought they aren't that be in the first place).
llvm-svn: 39433
2007-05-04 21:54:46 +00:00
|
|
|
}
|
|
|
|
|
2007-05-07 00:24:15 +00:00
|
|
|
// Unary Operators. 'Tok' is the token for the operator.
|
2007-09-16 03:34:24 +00:00
|
|
|
Action::ExprResult Sema::ActOnUnaryOp(SourceLocation OpLoc, tok::TokenKind Op,
|
2007-06-08 22:32:33 +00:00
|
|
|
ExprTy *input) {
|
|
|
|
Expr *Input = (Expr*)input;
|
2007-05-07 00:24:15 +00:00
|
|
|
UnaryOperator::Opcode Opc = ConvertTokenKindToUnaryOpcode(Op);
|
|
|
|
QualType resultType;
|
|
|
|
switch (Opc) {
|
|
|
|
default:
|
|
|
|
assert(0 && "Unimplemented unary expr!");
|
|
|
|
case UnaryOperator::PreInc:
|
|
|
|
case UnaryOperator::PreDec:
|
2007-06-08 22:32:33 +00:00
|
|
|
resultType = CheckIncrementDecrementOperand(Input, OpLoc);
|
2007-05-07 00:24:15 +00:00
|
|
|
break;
|
|
|
|
case UnaryOperator::AddrOf:
|
2007-06-08 22:32:33 +00:00
|
|
|
resultType = CheckAddressOfOperand(Input, OpLoc);
|
2007-05-07 00:24:15 +00:00
|
|
|
break;
|
|
|
|
case UnaryOperator::Deref:
|
2007-06-08 22:32:33 +00:00
|
|
|
resultType = CheckIndirectionOperand(Input, OpLoc);
|
2007-05-07 00:24:15 +00:00
|
|
|
break;
|
|
|
|
case UnaryOperator::Plus:
|
|
|
|
case UnaryOperator::Minus:
|
2007-07-16 21:54:35 +00:00
|
|
|
UsualUnaryConversions(Input);
|
|
|
|
resultType = Input->getType();
|
2007-05-07 00:24:15 +00:00
|
|
|
if (!resultType->isArithmeticType()) // C99 6.5.3.3p1
|
2007-05-16 18:09:54 +00:00
|
|
|
return Diag(OpLoc, diag::err_typecheck_unary_expr,
|
|
|
|
resultType.getAsString());
|
2007-05-07 00:24:15 +00:00
|
|
|
break;
|
|
|
|
case UnaryOperator::Not: // bitwise complement
|
2007-07-16 21:54:35 +00:00
|
|
|
UsualUnaryConversions(Input);
|
|
|
|
resultType = Input->getType();
|
2007-08-24 17:20:07 +00:00
|
|
|
// C99 6.5.3.3p1. We allow complex as a GCC extension.
|
|
|
|
if (!resultType->isIntegerType()) {
|
|
|
|
if (resultType->isComplexType())
|
|
|
|
// C99 does not support '~' for complex conjugation.
|
|
|
|
Diag(OpLoc, diag::ext_integer_complement_complex,
|
|
|
|
resultType.getAsString());
|
|
|
|
else
|
|
|
|
return Diag(OpLoc, diag::err_typecheck_unary_expr,
|
|
|
|
resultType.getAsString());
|
|
|
|
}
|
2007-05-07 00:24:15 +00:00
|
|
|
break;
|
|
|
|
case UnaryOperator::LNot: // logical negation
|
2007-06-04 22:22:31 +00:00
|
|
|
// Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5).
|
2007-07-16 21:54:35 +00:00
|
|
|
DefaultFunctionArrayConversion(Input);
|
|
|
|
resultType = Input->getType();
|
2007-05-07 00:24:15 +00:00
|
|
|
if (!resultType->isScalarType()) // C99 6.5.3.3p1
|
2007-05-16 18:09:54 +00:00
|
|
|
return Diag(OpLoc, diag::err_typecheck_unary_expr,
|
|
|
|
resultType.getAsString());
|
2007-06-02 19:11:33 +00:00
|
|
|
// LNot always has type int. C99 6.5.3.3p5.
|
|
|
|
resultType = Context.IntTy;
|
2007-05-07 00:24:15 +00:00
|
|
|
break;
|
|
|
|
case UnaryOperator::SizeOf:
|
2007-06-08 22:32:33 +00:00
|
|
|
resultType = CheckSizeOfAlignOfOperand(Input->getType(), OpLoc, true);
|
2007-05-15 02:32:35 +00:00
|
|
|
break;
|
2007-05-07 00:24:15 +00:00
|
|
|
case UnaryOperator::AlignOf:
|
2007-06-08 22:32:33 +00:00
|
|
|
resultType = CheckSizeOfAlignOfOperand(Input->getType(), OpLoc, false);
|
|
|
|
break;
|
2007-08-24 21:16:53 +00:00
|
|
|
case UnaryOperator::Real:
|
|
|
|
case UnaryOperator::Imag:
|
2007-08-24 21:41:10 +00:00
|
|
|
resultType = CheckRealImagOperand(Input, OpLoc);
|
2007-08-24 21:16:53 +00:00
|
|
|
break;
|
2007-06-08 22:32:33 +00:00
|
|
|
case UnaryOperator::Extension:
|
|
|
|
resultType = Input->getType();
|
2007-05-15 02:32:35 +00:00
|
|
|
break;
|
2007-05-07 00:24:15 +00:00
|
|
|
}
|
|
|
|
if (resultType.isNull())
|
|
|
|
return true;
|
2007-06-08 22:32:33 +00:00
|
|
|
return new UnaryOperator(Input, Opc, resultType, OpLoc);
|
2007-05-07 00:24:15 +00:00
|
|
|
}
|
2007-05-28 06:56:27 +00:00
|
|
|
|
2007-09-16 14:56:35 +00:00
|
|
|
/// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo".
|
|
|
|
Sema::ExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc,
|
2007-05-28 06:56:27 +00:00
|
|
|
SourceLocation LabLoc,
|
|
|
|
IdentifierInfo *LabelII) {
|
|
|
|
// Look up the record for this label identifier.
|
|
|
|
LabelStmt *&LabelDecl = LabelMap[LabelII];
|
|
|
|
|
|
|
|
// If we haven't seen this label yet, create a forward reference.
|
|
|
|
if (LabelDecl == 0)
|
|
|
|
LabelDecl = new LabelStmt(LabLoc, LabelII, 0);
|
|
|
|
|
|
|
|
// Create the AST node. The address of a label always has type 'void*'.
|
2007-08-03 17:31:20 +00:00
|
|
|
return new AddrLabelExpr(OpLoc, LabLoc, LabelDecl,
|
|
|
|
Context.getPointerType(Context.VoidTy));
|
2007-05-28 06:56:27 +00:00
|
|
|
}
|
|
|
|
|
2007-09-16 14:56:35 +00:00
|
|
|
Sema::ExprResult Sema::ActOnStmtExpr(SourceLocation LPLoc, StmtTy *substmt,
|
2007-07-24 16:58:17 +00:00
|
|
|
SourceLocation RPLoc) { // "({..})"
|
|
|
|
Stmt *SubStmt = static_cast<Stmt*>(substmt);
|
|
|
|
assert(SubStmt && isa<CompoundStmt>(SubStmt) && "Invalid action invocation!");
|
|
|
|
CompoundStmt *Compound = cast<CompoundStmt>(SubStmt);
|
|
|
|
|
|
|
|
// FIXME: there are a variety of strange constraints to enforce here, for
|
|
|
|
// example, it is not possible to goto into a stmt expression apparently.
|
|
|
|
// More semantic analysis is needed.
|
|
|
|
|
|
|
|
// FIXME: the last statement in the compount stmt has its value used. We
|
|
|
|
// should not warn about it being unused.
|
|
|
|
|
|
|
|
// If there are sub stmts in the compound stmt, take the type of the last one
|
|
|
|
// as the type of the stmtexpr.
|
|
|
|
QualType Ty = Context.VoidTy;
|
|
|
|
|
|
|
|
if (!Compound->body_empty())
|
|
|
|
if (Expr *LastExpr = dyn_cast<Expr>(Compound->body_back()))
|
|
|
|
Ty = LastExpr->getType();
|
|
|
|
|
|
|
|
return new StmtExpr(Compound, Ty, LPLoc, RPLoc);
|
|
|
|
}
|
2007-08-01 22:05:33 +00:00
|
|
|
|
2007-09-16 14:56:35 +00:00
|
|
|
Sema::ExprResult Sema::ActOnBuiltinOffsetOf(SourceLocation BuiltinLoc,
|
2007-08-30 17:45:32 +00:00
|
|
|
SourceLocation TypeLoc,
|
|
|
|
TypeTy *argty,
|
|
|
|
OffsetOfComponent *CompPtr,
|
|
|
|
unsigned NumComponents,
|
|
|
|
SourceLocation RPLoc) {
|
|
|
|
QualType ArgTy = QualType::getFromOpaquePtr(argty);
|
|
|
|
assert(!ArgTy.isNull() && "Missing type argument!");
|
|
|
|
|
|
|
|
// We must have at least one component that refers to the type, and the first
|
|
|
|
// one is known to be a field designator. Verify that the ArgTy represents
|
|
|
|
// a struct/union/class.
|
|
|
|
if (!ArgTy->isRecordType())
|
|
|
|
return Diag(TypeLoc, diag::err_offsetof_record_type,ArgTy.getAsString());
|
|
|
|
|
|
|
|
// Otherwise, create a compound literal expression as the base, and
|
|
|
|
// iteratively process the offsetof designators.
|
|
|
|
Expr *Res = new CompoundLiteralExpr(ArgTy, 0);
|
|
|
|
|
2007-08-31 21:49:13 +00:00
|
|
|
// offsetof with non-identifier designators (e.g. "offsetof(x, a.b[c])") are a
|
|
|
|
// GCC extension, diagnose them.
|
|
|
|
if (NumComponents != 1)
|
|
|
|
Diag(BuiltinLoc, diag::ext_offsetof_extended_field_designator,
|
|
|
|
SourceRange(CompPtr[1].LocStart, CompPtr[NumComponents-1].LocEnd));
|
|
|
|
|
2007-08-30 17:45:32 +00:00
|
|
|
for (unsigned i = 0; i != NumComponents; ++i) {
|
|
|
|
const OffsetOfComponent &OC = CompPtr[i];
|
|
|
|
if (OC.isBrackets) {
|
|
|
|
// Offset of an array sub-field. TODO: Should we allow vector elements?
|
|
|
|
const ArrayType *AT = Res->getType()->getAsArrayType();
|
|
|
|
if (!AT) {
|
|
|
|
delete Res;
|
|
|
|
return Diag(OC.LocEnd, diag::err_offsetof_array_type,
|
|
|
|
Res->getType().getAsString());
|
|
|
|
}
|
|
|
|
|
2007-08-30 17:59:59 +00:00
|
|
|
// FIXME: C++: Verify that operator[] isn't overloaded.
|
|
|
|
|
2007-08-30 17:45:32 +00:00
|
|
|
// C99 6.5.2.1p1
|
|
|
|
Expr *Idx = static_cast<Expr*>(OC.U.E);
|
|
|
|
if (!Idx->getType()->isIntegerType())
|
|
|
|
return Diag(Idx->getLocStart(), diag::err_typecheck_subscript,
|
|
|
|
Idx->getSourceRange());
|
|
|
|
|
|
|
|
Res = new ArraySubscriptExpr(Res, Idx, AT->getElementType(), OC.LocEnd);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
const RecordType *RC = Res->getType()->getAsRecordType();
|
|
|
|
if (!RC) {
|
|
|
|
delete Res;
|
|
|
|
return Diag(OC.LocEnd, diag::err_offsetof_record_type,
|
|
|
|
Res->getType().getAsString());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the decl corresponding to this.
|
|
|
|
RecordDecl *RD = RC->getDecl();
|
|
|
|
FieldDecl *MemberDecl = RD->getMember(OC.U.IdentInfo);
|
|
|
|
if (!MemberDecl)
|
|
|
|
return Diag(BuiltinLoc, diag::err_typecheck_no_member,
|
|
|
|
OC.U.IdentInfo->getName(),
|
|
|
|
SourceRange(OC.LocStart, OC.LocEnd));
|
2007-08-30 17:59:59 +00:00
|
|
|
|
|
|
|
// FIXME: C++: Verify that MemberDecl isn't a static field.
|
|
|
|
// FIXME: Verify that MemberDecl isn't a bitfield.
|
|
|
|
|
2007-08-30 17:45:32 +00:00
|
|
|
Res = new MemberExpr(Res, false, MemberDecl, OC.LocEnd);
|
|
|
|
}
|
|
|
|
|
|
|
|
return new UnaryOperator(Res, UnaryOperator::OffsetOf, Context.getSizeType(),
|
|
|
|
BuiltinLoc);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-09-16 14:56:35 +00:00
|
|
|
Sema::ExprResult Sema::ActOnTypesCompatibleExpr(SourceLocation BuiltinLoc,
|
2007-08-01 22:05:33 +00:00
|
|
|
TypeTy *arg1, TypeTy *arg2,
|
|
|
|
SourceLocation RPLoc) {
|
|
|
|
QualType argT1 = QualType::getFromOpaquePtr(arg1);
|
|
|
|
QualType argT2 = QualType::getFromOpaquePtr(arg2);
|
|
|
|
|
|
|
|
assert((!argT1.isNull() && !argT2.isNull()) && "Missing type argument(s)");
|
|
|
|
|
2007-08-30 17:45:32 +00:00
|
|
|
return new TypesCompatibleExpr(Context.IntTy, BuiltinLoc, argT1, argT2,RPLoc);
|
2007-08-01 22:05:33 +00:00
|
|
|
}
|
|
|
|
|
2007-09-16 14:56:35 +00:00
|
|
|
Sema::ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc, ExprTy *cond,
|
2007-08-03 21:21:27 +00:00
|
|
|
ExprTy *expr1, ExprTy *expr2,
|
|
|
|
SourceLocation RPLoc) {
|
|
|
|
Expr *CondExpr = static_cast<Expr*>(cond);
|
|
|
|
Expr *LHSExpr = static_cast<Expr*>(expr1);
|
|
|
|
Expr *RHSExpr = static_cast<Expr*>(expr2);
|
|
|
|
|
|
|
|
assert((CondExpr && LHSExpr && RHSExpr) && "Missing type argument(s)");
|
|
|
|
|
|
|
|
// The conditional expression is required to be a constant expression.
|
|
|
|
llvm::APSInt condEval(32);
|
|
|
|
SourceLocation ExpLoc;
|
|
|
|
if (!CondExpr->isIntegerConstantExpr(condEval, Context, &ExpLoc))
|
|
|
|
return Diag(ExpLoc, diag::err_typecheck_choose_expr_requires_constant,
|
|
|
|
CondExpr->getSourceRange());
|
|
|
|
|
|
|
|
// If the condition is > zero, then the AST type is the same as the LSHExpr.
|
|
|
|
QualType resType = condEval.getZExtValue() ? LHSExpr->getType() :
|
|
|
|
RHSExpr->getType();
|
|
|
|
return new ChooseExpr(BuiltinLoc, CondExpr, LHSExpr, RHSExpr, resType, RPLoc);
|
|
|
|
}
|
|
|
|
|
2007-08-21 17:43:55 +00:00
|
|
|
// TODO: Move this to SemaObjC.cpp
|
2007-08-22 15:14:15 +00:00
|
|
|
Sema::ExprResult Sema::ParseObjCStringLiteral(ExprTy *string) {
|
2007-08-21 17:43:55 +00:00
|
|
|
StringLiteral* S = static_cast<StringLiteral *>(string);
|
|
|
|
|
|
|
|
if (CheckBuiltinCFStringArgument(S))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
QualType t = Context.getCFConstantStringType();
|
|
|
|
t = t.getQualifiedType(QualType::Const);
|
|
|
|
t = Context.getPointerType(t);
|
|
|
|
|
|
|
|
return new ObjCStringLiteral(S, t);
|
|
|
|
}
|
2007-08-22 15:14:15 +00:00
|
|
|
|
|
|
|
Sema::ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc,
|
|
|
|
SourceLocation LParenLoc,
|
|
|
|
TypeTy *Ty,
|
|
|
|
SourceLocation RParenLoc) {
|
|
|
|
QualType EncodedType = QualType::getFromOpaquePtr(Ty);
|
|
|
|
|
|
|
|
QualType t = Context.getPointerType(Context.CharTy);
|
|
|
|
return new ObjCEncodeExpr(t, EncodedType, AtLoc, RParenLoc);
|
|
|
|
}
|
2007-09-17 21:01:15 +00:00
|
|
|
|
Add SelectorInfo (similar in spirit to IdentifierInfo). The key difference is SelectorInfo is not string-oriented, it is a unique aggregate of IdentifierInfo's (using a folding set). SelectorInfo also has a richer API that simplifies the parser/action interface. 3 noteworthy benefits:
#1: It is cleaner. I never "liked" storing keyword selectors (i.e. foo:bar:baz) in the IdentifierTable.
#2: It is more space efficient. Since Cocoa keyword selectors can be quite long, this technique is space saving. For Cocoa.h, pulling the keyword selectors out saves ~180k. The cost of the SelectorInfo data is ~100k. Saves ~80k, or 43%.
#3: It results in many API simplifications. Here are some highlights:
- Removed 3 actions (ActOnKeywordMessage, ActOnUnaryMessage, & one flavor of ObjcBuildMethodDeclaration that was specific to unary messages).
- Removed 3 funky structs from DeclSpec.h (ObjcKeywordMessage, ObjcKeywordDecl, and ObjcKeywordInfo).
- Removed 2 ivars and 2 constructors from ObjCMessageExpr (fyi, this space savings has not been measured).
I am happy with the way it turned out (though it took a bit more hacking than I expected). Given the central role of selectors in ObjC, making sure this is "right" will pay dividends later.
Thanks to Chris for talking this through with me and suggesting this approach.
llvm-svn: 42395
2007-09-27 14:38:14 +00:00
|
|
|
// ActOnClassMessage - used for both unary and keyword messages.
|
|
|
|
// ArgExprs is optional - if it is present, the number of expressions
|
|
|
|
// is obtained from Sel.getNumArgs().
|
|
|
|
Sema::ExprResult Sema::ActOnClassMessage(
|
2007-10-02 20:01:56 +00:00
|
|
|
IdentifierInfo *receiverName, Selector Sel,
|
Add SelectorInfo (similar in spirit to IdentifierInfo). The key difference is SelectorInfo is not string-oriented, it is a unique aggregate of IdentifierInfo's (using a folding set). SelectorInfo also has a richer API that simplifies the parser/action interface. 3 noteworthy benefits:
#1: It is cleaner. I never "liked" storing keyword selectors (i.e. foo:bar:baz) in the IdentifierTable.
#2: It is more space efficient. Since Cocoa keyword selectors can be quite long, this technique is space saving. For Cocoa.h, pulling the keyword selectors out saves ~180k. The cost of the SelectorInfo data is ~100k. Saves ~80k, or 43%.
#3: It results in many API simplifications. Here are some highlights:
- Removed 3 actions (ActOnKeywordMessage, ActOnUnaryMessage, & one flavor of ObjcBuildMethodDeclaration that was specific to unary messages).
- Removed 3 funky structs from DeclSpec.h (ObjcKeywordMessage, ObjcKeywordDecl, and ObjcKeywordInfo).
- Removed 2 ivars and 2 constructors from ObjCMessageExpr (fyi, this space savings has not been measured).
I am happy with the way it turned out (though it took a bit more hacking than I expected). Given the central role of selectors in ObjC, making sure this is "right" will pay dividends later.
Thanks to Chris for talking this through with me and suggesting this approach.
llvm-svn: 42395
2007-09-27 14:38:14 +00:00
|
|
|
SourceLocation lbrac, SourceLocation rbrac, ExprTy **Args)
|
2007-09-17 21:01:15 +00:00
|
|
|
{
|
2007-10-02 20:01:56 +00:00
|
|
|
assert(receiverName && "missing receiver class name");
|
2007-09-18 23:55:05 +00:00
|
|
|
|
2007-10-02 20:01:56 +00:00
|
|
|
ObjcInterfaceDecl* ClassDecl = getObjCInterfaceDecl(receiverName);
|
|
|
|
ObjcMethodDecl *Method = ClassDecl->lookupClassMethod(Sel);
|
|
|
|
assert(Method && "missing method declaration");
|
|
|
|
QualType retType = Method->getMethodType();
|
|
|
|
// Expr *RExpr = global reference to the class symbol...
|
Add SelectorInfo (similar in spirit to IdentifierInfo). The key difference is SelectorInfo is not string-oriented, it is a unique aggregate of IdentifierInfo's (using a folding set). SelectorInfo also has a richer API that simplifies the parser/action interface. 3 noteworthy benefits:
#1: It is cleaner. I never "liked" storing keyword selectors (i.e. foo:bar:baz) in the IdentifierTable.
#2: It is more space efficient. Since Cocoa keyword selectors can be quite long, this technique is space saving. For Cocoa.h, pulling the keyword selectors out saves ~180k. The cost of the SelectorInfo data is ~100k. Saves ~80k, or 43%.
#3: It results in many API simplifications. Here are some highlights:
- Removed 3 actions (ActOnKeywordMessage, ActOnUnaryMessage, & one flavor of ObjcBuildMethodDeclaration that was specific to unary messages).
- Removed 3 funky structs from DeclSpec.h (ObjcKeywordMessage, ObjcKeywordDecl, and ObjcKeywordInfo).
- Removed 2 ivars and 2 constructors from ObjCMessageExpr (fyi, this space savings has not been measured).
I am happy with the way it turned out (though it took a bit more hacking than I expected). Given the central role of selectors in ObjC, making sure this is "right" will pay dividends later.
Thanks to Chris for talking this through with me and suggesting this approach.
llvm-svn: 42395
2007-09-27 14:38:14 +00:00
|
|
|
Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
|
2007-10-10 23:42:28 +00:00
|
|
|
return new ObjCMessageExpr(receiverName, Sel, retType, lbrac, rbrac,
|
|
|
|
ArgExprs);
|
2007-09-17 21:01:15 +00:00
|
|
|
}
|
|
|
|
|
Add SelectorInfo (similar in spirit to IdentifierInfo). The key difference is SelectorInfo is not string-oriented, it is a unique aggregate of IdentifierInfo's (using a folding set). SelectorInfo also has a richer API that simplifies the parser/action interface. 3 noteworthy benefits:
#1: It is cleaner. I never "liked" storing keyword selectors (i.e. foo:bar:baz) in the IdentifierTable.
#2: It is more space efficient. Since Cocoa keyword selectors can be quite long, this technique is space saving. For Cocoa.h, pulling the keyword selectors out saves ~180k. The cost of the SelectorInfo data is ~100k. Saves ~80k, or 43%.
#3: It results in many API simplifications. Here are some highlights:
- Removed 3 actions (ActOnKeywordMessage, ActOnUnaryMessage, & one flavor of ObjcBuildMethodDeclaration that was specific to unary messages).
- Removed 3 funky structs from DeclSpec.h (ObjcKeywordMessage, ObjcKeywordDecl, and ObjcKeywordInfo).
- Removed 2 ivars and 2 constructors from ObjCMessageExpr (fyi, this space savings has not been measured).
I am happy with the way it turned out (though it took a bit more hacking than I expected). Given the central role of selectors in ObjC, making sure this is "right" will pay dividends later.
Thanks to Chris for talking this through with me and suggesting this approach.
llvm-svn: 42395
2007-09-27 14:38:14 +00:00
|
|
|
// ActOnInstanceMessage - used for both unary and keyword messages.
|
|
|
|
// ArgExprs is optional - if it is present, the number of expressions
|
|
|
|
// is obtained from Sel.getNumArgs().
|
|
|
|
Sema::ExprResult Sema::ActOnInstanceMessage(
|
2007-09-28 22:22:11 +00:00
|
|
|
ExprTy *receiver, Selector Sel,
|
Add SelectorInfo (similar in spirit to IdentifierInfo). The key difference is SelectorInfo is not string-oriented, it is a unique aggregate of IdentifierInfo's (using a folding set). SelectorInfo also has a richer API that simplifies the parser/action interface. 3 noteworthy benefits:
#1: It is cleaner. I never "liked" storing keyword selectors (i.e. foo:bar:baz) in the IdentifierTable.
#2: It is more space efficient. Since Cocoa keyword selectors can be quite long, this technique is space saving. For Cocoa.h, pulling the keyword selectors out saves ~180k. The cost of the SelectorInfo data is ~100k. Saves ~80k, or 43%.
#3: It results in many API simplifications. Here are some highlights:
- Removed 3 actions (ActOnKeywordMessage, ActOnUnaryMessage, & one flavor of ObjcBuildMethodDeclaration that was specific to unary messages).
- Removed 3 funky structs from DeclSpec.h (ObjcKeywordMessage, ObjcKeywordDecl, and ObjcKeywordInfo).
- Removed 2 ivars and 2 constructors from ObjCMessageExpr (fyi, this space savings has not been measured).
I am happy with the way it turned out (though it took a bit more hacking than I expected). Given the central role of selectors in ObjC, making sure this is "right" will pay dividends later.
Thanks to Chris for talking this through with me and suggesting this approach.
llvm-svn: 42395
2007-09-27 14:38:14 +00:00
|
|
|
SourceLocation lbrac, SourceLocation rbrac, ExprTy **Args)
|
|
|
|
{
|
2007-09-18 23:55:05 +00:00
|
|
|
assert(receiver && "missing receiver expression");
|
|
|
|
|
|
|
|
Expr *RExpr = static_cast<Expr *>(receiver);
|
2007-10-02 20:01:56 +00:00
|
|
|
QualType receiverType = RExpr->getType();
|
2007-10-10 21:53:07 +00:00
|
|
|
QualType returnType;
|
|
|
|
|
|
|
|
if (receiverType == GetObjcIdType()) {
|
2007-10-14 23:13:51 +00:00
|
|
|
ObjcMethodDecl *Method = InstanceMethodPool[Sel].Method;
|
|
|
|
// FIXME: emit a diagnostic. For now, I want a hard error...
|
|
|
|
assert(Method && "missing method declaration");
|
|
|
|
returnType = Method->getMethodType();
|
2007-10-10 21:53:07 +00:00
|
|
|
} else {
|
2007-10-10 23:42:28 +00:00
|
|
|
// FIXME (snaroff): checking in this code from Patrick. Needs to be
|
|
|
|
// revisited. how do we get the ClassDecl from the receiver expression?
|
2007-10-10 21:53:07 +00:00
|
|
|
while (receiverType->isPointerType()) {
|
2007-10-10 23:42:28 +00:00
|
|
|
PointerType *pointerType =
|
|
|
|
static_cast<PointerType*>(receiverType.getTypePtr());
|
2007-10-10 21:53:07 +00:00
|
|
|
receiverType = pointerType->getPointeeType();
|
|
|
|
}
|
2007-10-10 23:42:28 +00:00
|
|
|
assert(ObjcInterfaceType::classof(receiverType.getTypePtr()) &&
|
|
|
|
"bad receiver type");
|
2007-10-10 21:53:07 +00:00
|
|
|
ObjcInterfaceDecl* ClassDecl = static_cast<ObjcInterfaceType*>(
|
|
|
|
receiverType.getTypePtr())->getDecl();
|
|
|
|
ObjcMethodDecl *Method = ClassDecl->lookupInstanceMethod(Sel);
|
2007-10-14 23:13:51 +00:00
|
|
|
// FIXME: emit a diagnostic. For now, I want a hard error...
|
2007-10-10 21:53:07 +00:00
|
|
|
assert(Method && "missing method declaration");
|
|
|
|
returnType = Method->getMethodType();
|
2007-10-02 20:01:56 +00:00
|
|
|
}
|
Add SelectorInfo (similar in spirit to IdentifierInfo). The key difference is SelectorInfo is not string-oriented, it is a unique aggregate of IdentifierInfo's (using a folding set). SelectorInfo also has a richer API that simplifies the parser/action interface. 3 noteworthy benefits:
#1: It is cleaner. I never "liked" storing keyword selectors (i.e. foo:bar:baz) in the IdentifierTable.
#2: It is more space efficient. Since Cocoa keyword selectors can be quite long, this technique is space saving. For Cocoa.h, pulling the keyword selectors out saves ~180k. The cost of the SelectorInfo data is ~100k. Saves ~80k, or 43%.
#3: It results in many API simplifications. Here are some highlights:
- Removed 3 actions (ActOnKeywordMessage, ActOnUnaryMessage, & one flavor of ObjcBuildMethodDeclaration that was specific to unary messages).
- Removed 3 funky structs from DeclSpec.h (ObjcKeywordMessage, ObjcKeywordDecl, and ObjcKeywordInfo).
- Removed 2 ivars and 2 constructors from ObjCMessageExpr (fyi, this space savings has not been measured).
I am happy with the way it turned out (though it took a bit more hacking than I expected). Given the central role of selectors in ObjC, making sure this is "right" will pay dividends later.
Thanks to Chris for talking this through with me and suggesting this approach.
llvm-svn: 42395
2007-09-27 14:38:14 +00:00
|
|
|
Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
|
2007-10-02 20:01:56 +00:00
|
|
|
return new ObjCMessageExpr(RExpr, Sel, returnType, lbrac, rbrac, ArgExprs);
|
2007-09-17 21:01:15 +00:00
|
|
|
}
|