"git@repo.hca.bsc.es:rferrer/llvm-epi-0.8.git" did not exist on "7e7d5eefb2023ccf45c76edf48eeffc77a8d9f9e"
Newer
Older
//===--- SemaExpr.cpp - Semantic Analysis for Expressions -----------------===//
//
// The LLVM Compiler Infrastructure
//
// This file 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"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Scope.h"
using namespace clang;
//===----------------------------------------------------------------------===//
// Standard Promotions and Conversions
//===----------------------------------------------------------------------===//
/// DefaultFunctionArrayConversion (C99 6.3.2.1p3, C99 6.3.2.1p4).
void Sema::DefaultFunctionArrayConversion(Expr *&E) {
QualType Ty = E->getType();
assert(!Ty.isNull() && "DefaultFunctionArrayConversion - missing type");
if (const ReferenceType *ref = Ty->getAsReferenceType()) {
ImpCastExprToType(E, ref->getPointeeType()); // C++ [expr]
Ty = E->getType();
}
if (Ty->isFunctionType())
ImpCastExprToType(E, Context.getPointerType(Ty));
Chris Lattner
committed
else if (Ty->isArrayType()) {
// In C90 mode, arrays only promote to pointers if the array expression is
// an lvalue. The relevant legalese is C90 6.2.2.1p3: "an lvalue that has
// type 'array of type' is converted to an expression that has type 'pointer
// to type'...". In C99 this was changed to: C99 6.3.2.1p3: "an expression
// that has type 'array of type' ...". The relevant change is "an lvalue"
// (C90) to "an expression" (C99).
//
// C++ 4.2p1:
// An lvalue or rvalue of type "array of N T" or "array of unknown bound of
// T" can be converted to an rvalue of type "pointer to T".
//
if (getLangOptions().C99 || getLangOptions().CPlusPlus ||
E->isLvalue(Context) == Expr::LV_Valid)
Chris Lattner
committed
ImpCastExprToType(E, Context.getArrayDecayedType(Ty));
}
}
/// UsualUnaryConversions - 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.
Expr *Sema::UsualUnaryConversions(Expr *&Expr) {
QualType Ty = Expr->getType();
assert(!Ty.isNull() && "UsualUnaryConversions - missing type");
if (const ReferenceType *Ref = Ty->getAsReferenceType()) {
ImpCastExprToType(Expr, Ref->getPointeeType()); // C++ [expr]
Ty = Expr->getType();
}
if (Ty->isPromotableIntegerType()) // C99 6.3.1.1p2
ImpCastExprToType(Expr, Context.IntTy);
else
DefaultFunctionArrayConversion(Expr);
return Expr;
}
/// DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that
/// do not have a prototype. Arguments that have type float are promoted to
/// double. All other argument types are converted by UsualUnaryConversions().
void Sema::DefaultArgumentPromotion(Expr *&Expr) {
QualType Ty = Expr->getType();
assert(!Ty.isNull() && "DefaultArgumentPromotion - missing type");
// If this is a 'float' (CVR qualified or typedef) promote to double.
if (const BuiltinType *BT = Ty->getAsBuiltinType())
if (BT->getKind() == BuiltinType::Float)
return ImpCastExprToType(Expr, Context.DoubleTy);
UsualUnaryConversions(Expr);
}
/// UsualArithmeticConversions - Performs various conversions that are common to
/// 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.
/// FIXME: verify the conversion rules for "complex int" are consistent with
/// GCC.
QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
bool isCompAssign) {
if (!isCompAssign) {
UsualUnaryConversions(lhsExpr);
UsualUnaryConversions(rhsExpr);
}
// For conversion purposes, we ignore any qualifiers.
// For example, "const float" and "float" are equivalent.
QualType lhs =
Context.getCanonicalType(lhsExpr->getType()).getUnqualifiedType();
QualType rhs =
Context.getCanonicalType(rhsExpr->getType()).getUnqualifiedType();
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
// If both types are identical, no conversion is needed.
if (lhs == rhs)
return lhs;
// 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).
if (!lhs->isArithmeticType() || !rhs->isArithmeticType())
return lhs;
// At this point, we have two different arithmetic types.
// 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.
if (rhs->isIntegerType() || rhs->isComplexIntegerType()) {
// convert the rhs to the lhs complex type.
if (!isCompAssign) ImpCastExprToType(rhsExpr, lhs);
return lhs;
}
if (lhs->isIntegerType() || lhs->isComplexIntegerType()) {
// convert the lhs to the rhs complex type.
if (!isCompAssign) ImpCastExprToType(lhsExpr, rhs);
return rhs;
}
// 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".
int result = Context.getFloatingTypeOrder(lhs, rhs);
if (result > 0) { // The left side is bigger, convert rhs.
rhs = Context.getFloatingTypeOfSizeWithinDomain(lhs, rhs);
if (!isCompAssign)
ImpCastExprToType(rhsExpr, rhs);
} else if (result < 0) { // The right side is bigger, convert lhs.
lhs = Context.getFloatingTypeOfSizeWithinDomain(rhs, lhs);
if (!isCompAssign)
ImpCastExprToType(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".
if (!isCompAssign)
ImpCastExprToType(lhsExpr, rhs);
return rhs;
} else { // handle "_Complex double, double".
if (!isCompAssign)
ImpCastExprToType(rhsExpr, lhs);
return lhs;
}
}
return lhs; // The domain/size match exactly.
}
// 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.
if (rhs->isIntegerType() || rhs->isComplexIntegerType()) {
// convert rhs to the lhs floating point type.
if (!isCompAssign) ImpCastExprToType(rhsExpr, lhs);
return lhs;
}
if (lhs->isIntegerType() || lhs->isComplexIntegerType()) {
// convert lhs to the rhs floating point type.
if (!isCompAssign) ImpCastExprToType(lhsExpr, rhs);
return rhs;
}
// We have two real floating types, float/complex combos were handled above.
// Convert the smaller operand to the bigger result.
int result = Context.getFloatingTypeOrder(lhs, rhs);
if (result > 0) { // convert the rhs
if (!isCompAssign) ImpCastExprToType(rhsExpr, lhs);
return lhs;
}
if (result < 0) { // convert the lhs
if (!isCompAssign) ImpCastExprToType(lhsExpr, rhs); // convert the lhs
return rhs;
}
assert(0 && "Sema::UsualArithmeticConversions(): illegal float comparison");
}
if (lhs->isComplexIntegerType() || rhs->isComplexIntegerType()) {
// Handle GCC complex int extension.
const ComplexType *lhsComplexInt = lhs->getAsComplexIntegerType();
const ComplexType *rhsComplexInt = rhs->getAsComplexIntegerType();
if (lhsComplexInt && rhsComplexInt) {
if (Context.getIntegerTypeOrder(lhsComplexInt->getElementType(),
rhsComplexInt->getElementType()) >= 0) {
// convert the rhs
if (!isCompAssign) ImpCastExprToType(rhsExpr, lhs);
return lhs;
}
if (!isCompAssign)
ImpCastExprToType(lhsExpr, rhs); // convert the lhs
return rhs;
} else if (lhsComplexInt && rhs->isIntegerType()) {
// convert the rhs to the lhs complex type.
if (!isCompAssign) ImpCastExprToType(rhsExpr, lhs);
return lhs;
} else if (rhsComplexInt && lhs->isIntegerType()) {
// convert the lhs to the rhs complex type.
if (!isCompAssign) ImpCastExprToType(lhsExpr, rhs);
return rhs;
}
}
// Finally, we have two differing integer types.
// The rules for this case are in C99 6.3.1.8
int compare = Context.getIntegerTypeOrder(lhs, rhs);
bool lhsSigned = lhs->isSignedIntegerType(),
rhsSigned = rhs->isSignedIntegerType();
QualType destType;
if (lhsSigned == rhsSigned) {
// Same signedness; use the higher-ranked type
destType = compare >= 0 ? lhs : rhs;
} else if (compare != (lhsSigned ? 1 : -1)) {
// The unsigned type has greater than or equal rank to the
// signed type, so use the unsigned type
destType = lhsSigned ? rhs : lhs;
} else if (Context.getIntWidth(lhs) != Context.getIntWidth(rhs)) {
// The two types are different widths; if we are here, that
// means the signed type is larger than the unsigned type, so
// use the signed type.
destType = lhsSigned ? lhs : rhs;
} else {
// The signed type is higher-ranked than the unsigned type,
// but isn't actually any bigger (like unsigned int and long
// on most 32-bit systems). Use the unsigned type corresponding
// to the signed type.
destType = Context.getCorrespondingUnsignedType(lhsSigned ? lhs : rhs);
}
if (!isCompAssign) {
ImpCastExprToType(lhsExpr, destType);
ImpCastExprToType(rhsExpr, destType);
}
return destType;
}
//===----------------------------------------------------------------------===//
// Semantic Analysis for various Expression Types
//===----------------------------------------------------------------------===//
/// ActOnStringLiteral - The specified tokens were lexed as pasted string
/// 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
Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) {
assert(NumStringToks && "Must have at least one string!");
StringLiteralParser Literal(StringToks, NumStringToks, PP, Context.Target);
if (Literal.hadError)
return ExprResult(true);
Chris Lattner
committed
llvm::SmallVector<SourceLocation, 4> StringTokLocs;
for (unsigned i = 0; i != NumStringToks; ++i)
StringTokLocs.push_back(StringToks[i].getLocation());
// Verify that pascal strings aren't too large.
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()));
QualType StrTy = Context.CharTy;
if (Literal.AnyWide) StrTy = Context.getWCharType();
if (Literal.Pascal) StrTy = Context.UnsignedCharTy;
Douglas Gregor
committed
// A C++ string literal has a const-qualified element type (C++ 2.13.4p1).
if (getLangOptions().CPlusPlus)
StrTy.addConst();
// Get an array type for the string, according to C99 6.4.5. This includes
// the nul terminator character as well as the string length for pascal
// strings.
StrTy = Context.getConstantArrayType(StrTy,
llvm::APInt(32, Literal.GetStringLength()+1),
ArrayType::Normal, 0);
// Pass &StringTokLocs[0], StringTokLocs.size() to factory!
return new StringLiteral(Literal.GetString(), Literal.GetStringLength(),
Literal.AnyWide, StrTy,
Steve Naroff
committed
/// DeclDefinedWithinScope - Return true if the specified decl is defined at or
/// within the 'Within' scope. The current Scope is CurScope.
///
/// FIXME: This method is extremely inefficient (linear scan), this should not
/// be used in common cases. Replace with the more modern DeclContext. We need
/// to make sure both assignments below produce an error.
///
/// int main(int argc) {
/// int xx;
/// ^(int X) {
/// xx = 4; // error (variable is not assignable)
/// argc = 3; // no error.
/// };
/// }
Steve Naroff
committed
///
static bool DeclDefinedWithinScope(ScopedDecl *D, Scope *Within,
Scope *CurScope) {
while (1) {
assert(CurScope && "CurScope not nested within 'Within'?");
// Check this scope for the decl.
if (CurScope->isDeclScope(D)) return true;
if (CurScope == Within) return false;
CurScope = CurScope->getParent();
}
}
Chris Lattner
committed
/// ActOnIdentifierExpr - The parser read an identifier in expression context,
/// validate it per-C99 6.5.1. HasTrailingLParen indicates whether this
IdentifierInfo &II,
bool HasTrailingLParen) {
// Could be enum-constant, value decl, instance variable, etc.
// If this reference is in an Objective-C method, then ivar lookup happens as
// well.
Argyrios Kyrtzidis
committed
if (getCurMethodDecl()) {
Steve Naroff
committed
ScopedDecl *SD = dyn_cast_or_null<ScopedDecl>(D);
// There are two cases to handle here. 1) scoped lookup could have failed,
// in which case we should look for an ivar. 2) scoped lookup could have
// found a decl, but that decl is outside the current method (i.e. a global
// variable). In these two cases, we do a lookup for an ivar with this
// name, if the lookup suceeds, we replace it our current decl.
Steve Naroff
committed
if (SD == 0 || SD->isDefinedOutsideFunctionOrMethod()) {
Argyrios Kyrtzidis
committed
ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface();
if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(&II)) {
// FIXME: This should use a new expr for a direct reference, don't turn
// this into Self->ivar, just return a BareIVarExpr or something.
IdentifierInfo &II = Context.Idents.get("self");
ExprResult SelfExpr = ActOnIdentifierExpr(S, Loc, II, false);
return new ObjCIvarRefExpr(IV, IV->getType(), Loc,
static_cast<Expr*>(SelfExpr.Val), true, true);
}
}
// Needed to implement property "super.method" notation.
if (SD == 0 && &II == SuperID) {
Steve Naroff
committed
QualType T = Context.getPointerType(Context.getObjCInterfaceType(
Argyrios Kyrtzidis
committed
getCurMethodDecl()->getClassInterface()));
return new PredefinedExpr(Loc, T, PredefinedExpr::ObjCSuper);
Steve Naroff
committed
}
// If we are parsing a block, check the block parameter list.
if (CurBlock) {
Steve Naroff
committed
BlockSemaInfo *BLK = CurBlock;
do {
for (unsigned i = 0, e = BLK->Params.size(); i != e && D == 0; ++i)
if (BLK->Params[i]->getIdentifier() == &II)
D = BLK->Params[i];
if (D)
break; // Found!
} while ((BLK = BLK->PrevBlockInfo)); // Look through any enclosing blocks.
if (D == 0) {
// Otherwise, this could be an implicitly declared function reference (legal
// in C90, extension in C99).
if (HasTrailingLParen &&
!getLangOptions().CPlusPlus) // Not in C++.
D = ImplicitlyDefineFunction(Loc, II, S);
// If this name wasn't predeclared and if this is not a function call,
// diagnose the problem.
if (CXXFieldDecl *FD = dyn_cast<CXXFieldDecl>(D)) {
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext)) {
if (MD->isStatic())
// "invalid use of member 'x' in static member function"
return Diag(Loc, diag::err_invalid_member_use_in_static_method,
FD->getName());
if (cast<CXXRecordDecl>(MD->getParent()) != FD->getParent())
// "invalid use of nonstatic data member 'x'"
return Diag(Loc, diag::err_invalid_non_static_member_use,
FD->getName());
if (FD->isInvalidDecl())
return true;
// FIXME: Use DeclRefExpr or a new Expr for a direct CXXField reference.
ExprResult ThisExpr = ActOnCXXThis(SourceLocation());
return new MemberExpr(static_cast<Expr*>(ThisExpr.Val),
true, FD, Loc, FD->getType());
}
return Diag(Loc, diag::err_invalid_non_static_member_use, FD->getName());
}
if (isa<ObjCInterfaceDecl>(D))
return Diag(Loc, diag::err_unexpected_interface, II.getName());
if (isa<NamespaceDecl>(D))
return Diag(Loc, diag::err_unexpected_namespace, II.getName());
Steve Naroff
committed
// Make the DeclRefExpr or BlockDeclRefExpr for the decl.
ValueDecl *VD = cast<ValueDecl>(D);
// check if referencing an identifier with __attribute__((deprecated)).
if (VD->getAttr<DeprecatedAttr>())
Diag(Loc, diag::warn_deprecated, VD->getName());
// Only create DeclRefExpr's for valid Decl's.
if (VD->isInvalidDecl())
return true;
// If this reference is not in a block or if the referenced variable is
// within the block, create a normal DeclRefExpr.
//
// FIXME: This will create BlockDeclRefExprs for global variables,
// function references, etc which is suboptimal :) and breaks
Steve Naroff
committed
// things like "integer constant expression" tests.
//
if (!CurBlock || DeclDefinedWithinScope(VD, CurBlock->TheScope, S) ||
Steve Naroff
committed
isa<EnumConstantDecl>(VD) || isa<ParmVarDecl>(VD))
Steve Naroff
committed
return new DeclRefExpr(VD, VD->getType(), Loc);
// If we are in a block and the variable is outside the current block,
// bind the variable reference with a BlockDeclRefExpr.
// The BlocksAttr indicates the variable is bound by-reference.
if (VD->getAttr<BlocksAttr>())
return new BlockDeclRefExpr(VD, VD->getType(), Loc, true);
Steve Naroff
committed
// Variable will be bound by-copy, make it const within the closure.
VD->getType().addConst();
Steve Naroff
committed
return new BlockDeclRefExpr(VD, VD->getType(), Loc, false);
Chris Lattner
committed
Sema::ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc,
Anders Carlsson
committed
tok::TokenKind Kind) {
Anders Carlsson
committed
Chris Lattner
committed
switch (Kind) {
default: assert(0 && "Unknown simple primary expr!");
case tok::kw___func__: IT = PredefinedExpr::Func; break; // [C99 6.4.2.2]
case tok::kw___FUNCTION__: IT = PredefinedExpr::Function; break;
case tok::kw___PRETTY_FUNCTION__: IT = PredefinedExpr::PrettyFunction; break;
Chris Lattner
committed
}
// Verify that this is in a function context.
Argyrios Kyrtzidis
committed
if (getCurFunctionDecl() == 0 && getCurMethodDecl() == 0)
return Diag(Loc, diag::err_predef_outside_function);
Anders Carlsson
committed
// Pre-defined identifiers are of type char[x], where x is the length of the
// string.
Argyrios Kyrtzidis
committed
if (getCurFunctionDecl())
Length = getCurFunctionDecl()->getIdentifier()->getLength();
Argyrios Kyrtzidis
committed
Length = getCurMethodDecl()->getSynthesizedMethodSize();
QualType ResTy = Context.CharTy.getQualifiedType(QualType::Const);
ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0);
return new PredefinedExpr(Loc, ResTy, IT);
Chris Lattner
committed
}
Sema::ExprResult Sema::ActOnCharacterConstant(const Token &Tok) {
Chris Lattner
committed
llvm::SmallString<16> CharBuffer;
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);
QualType type = getLangOptions().CPlusPlus ? Context.CharTy : Context.IntTy;
return new CharacterLiteral(Literal.getValue(), Literal.isWide(), type,
Tok.getLocation());
Action::ExprResult Sema::ActOnNumericConstant(const Token &Tok) {
// 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 *Ty = PP.getSourceManager().getCharacterData(Tok.getLocation());
Chris Lattner
committed
unsigned IntSize =static_cast<unsigned>(Context.getTypeSize(Context.IntTy));
return ExprResult(new IntegerLiteral(llvm::APInt(IntSize, *Ty-'0'),
Chris Lattner
committed
Context.IntTy,
Chris Lattner
committed
llvm::SmallString<512> IntegerBuffer;
IntegerBuffer.resize(Tok.getLength());
const char *ThisTokBegin = &IntegerBuffer[0];
Chris Lattner
committed
// Get the spelling of the token, which eliminates trigraphs, etc.
NumericLiteralParser Literal(ThisTokBegin, ThisTokBegin+ActualLength,
Chris Lattner
committed
Expr *Res;
if (Literal.isFloatingLiteral()) {
QualType Ty;
Ty = Context.FloatTy;
Ty = Context.DoubleTy;
Ty = Context.LongDoubleTy;
const llvm::fltSemantics &Format = Context.getFloatTypeSemantics(Ty);
// isExact will be set by GetFloatValue().
bool isExact = false;
Res = new FloatingLiteral(Literal.GetFloatValue(Format, &isExact), &isExact,
Ty, Tok.getLocation());
} else if (!Literal.isIntegerLiteral()) {
return ExprResult(true);
} else {
Chris Lattner
committed
// long long is a C99 feature.
if (!getLangOptions().C99 && !getLangOptions().CPlusPlus0x &&
Diag(Tok.getLocation(), diag::ext_longlong);
Chris Lattner
committed
// Get the value in the widest-possible width.
llvm::APInt ResultVal(Context.Target.getIntMaxTWidth(), 0);
Chris Lattner
committed
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);
Ty = Context.UnsignedLongLongTy;
assert(Context.getTypeSize(Ty) == ResultVal.getBitWidth() &&
"long long is not intmax_t?");
Chris Lattner
committed
// 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.
unsigned Width = 0;
Chris Lattner
committed
if (!Literal.isLong && !Literal.isLongLong) {
// Are int/unsigned possibilities?
unsigned IntSize = Context.Target.getIntWidth();
Chris Lattner
committed
// 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)
Chris Lattner
committed
else if (AllowUnsigned)
Ty = Context.UnsignedIntTy;
Width = IntSize;
Chris Lattner
committed
}
}
// Are long/unsigned long possibilities?
if (Ty.isNull() && !Literal.isLongLong) {
unsigned LongSize = Context.Target.getLongWidth();
Chris Lattner
committed
// 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)
Chris Lattner
committed
else if (AllowUnsigned)
Ty = Context.UnsignedLongTy;
Width = LongSize;
Chris Lattner
committed
}
}
// Finally, check long long if needed.
unsigned LongLongSize = Context.Target.getLongLongWidth();
Chris Lattner
committed
// 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)
Ty = Context.LongLongTy;
Chris Lattner
committed
else if (AllowUnsigned)
Ty = Context.UnsignedLongLongTy;
Width = LongLongSize;
Chris Lattner
committed
}
}
// 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.
Chris Lattner
committed
Diag(Tok.getLocation(), diag::warn_integer_too_large_for_signed);
Ty = Context.UnsignedLongLongTy;
Width = Context.Target.getLongLongWidth();
Chris Lattner
committed
}
if (ResultVal.getBitWidth() != Width)
ResultVal.trunc(Width);
Chris Lattner
committed
Res = new IntegerLiteral(ResultVal, Ty, Tok.getLocation());
// If this is an imaginary literal, create the ImaginaryLiteral wrapper.
if (Literal.isImaginary)
Res = new ImaginaryLiteral(Res, Context.getComplexType(Res->getType()));
return Res;
Chris Lattner
committed
}
Action::ExprResult Sema::ActOnParenExpr(SourceLocation L, SourceLocation R,
Chris Lattner
committed
ExprTy *Val) {
Expr *E = (Expr *)Val;
assert((E != 0) && "ActOnParenExpr() missing expr");
return new ParenExpr(L, R, E);
Chris Lattner
committed
}
/// The UsualUnaryConversions() function is *not* called by this routine.
SourceLocation OpLoc,
const SourceRange &ExprRange,
bool isSizeof) {
// C99 6.5.3.4p1:
if (isa<FunctionType>(exprType) && isSizeof)
// alignof(function) is allowed.
Diag(OpLoc, diag::ext_sizeof_function_type, ExprRange);
Diag(OpLoc, diag::ext_sizeof_void_type, isSizeof ? "sizeof" : "__alignof",
ExprRange);
else if (exprType->isIncompleteType()) {
Diag(OpLoc, isSizeof ? diag::err_sizeof_incomplete_type :
diag::err_alignof_incomplete_type,
exprType.getAsString(), ExprRange);
return QualType(); // error
}
// C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
return Context.getSizeType();
}
Chris Lattner
committed
Action::ExprResult Sema::
ActOnSizeOfAlignOfTypeExpr(SourceLocation OpLoc, bool isSizeof,
// If error parsing type, ignore.
if (Ty == 0) return true;
// Verify that this is a valid expression.
QualType resultType =
CheckSizeOfAlignOfOperand(ArgTy, OpLoc, SourceRange(LPLoc, RPLoc),isSizeof);
return new SizeOfAlignOfTypeExpr(isSizeof, ArgTy, resultType, OpLoc, RPLoc);
Chris Lattner
committed
}
QualType Sema::CheckRealImagOperand(Expr *&V, SourceLocation Loc) {
DefaultFunctionArrayConversion(V);
// These operators return the element type of a complex type.
if (const ComplexType *CT = V->getType()->getAsComplexType())
return CT->getElementType();
// 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();
Chris Lattner
committed
Action::ExprResult Sema::ActOnPostfixUnaryOp(SourceLocation OpLoc,
Chris Lattner
committed
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;
}
QualType result = CheckIncrementDecrementOperand((Expr *)Input, OpLoc);
Chris Lattner
committed
}
Action::ExprResult Sema::
ActOnArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc,
Chris Lattner
committed
ExprTy *Idx, SourceLocation RLoc) {
Chris Lattner
committed
Expr *LHSExp = static_cast<Expr*>(Base), *RHSExp = static_cast<Expr*>(Idx);
Chris Lattner
committed
// Perform default conversions.
DefaultFunctionArrayConversion(LHSExp);
DefaultFunctionArrayConversion(RHSExp);
Chris Lattner
committed
Chris Lattner
committed
QualType LHSTy = LHSExp->getType(), RHSTy = RHSExp->getType();
// C99 6.5.2.1p2: the expression e1[e2] is by definition precisely equivalent
// to the expression *((e1)+(e2)). This means the array "Base" may actually be
// in the subscript position. As a result, we need to derive the array base
// and index from the expression types.
Chris Lattner
committed
Expr *BaseExpr, *IndexExpr;
QualType ResultType;
if (const PointerType *PTy = LHSTy->getAsPointerType()) {
Chris Lattner
committed
BaseExpr = LHSExp;
IndexExpr = RHSExp;
// FIXME: need to deal with const...
ResultType = PTy->getPointeeType();
} else if (const PointerType *PTy = RHSTy->getAsPointerType()) {
Chris Lattner
committed
// Handle the uncommon case of "123[Ptr]".
Chris Lattner
committed
BaseExpr = RHSExp;
IndexExpr = LHSExp;
// FIXME: need to deal with const...
ResultType = PTy->getPointeeType();
} else if (const VectorType *VTy = LHSTy->getAsVectorType()) {
BaseExpr = LHSExp; // vectors: V[123]
Chris Lattner
committed
IndexExpr = RHSExp;
// Component access limited to variables (reject vec4.rg[1]).
if (!isa<DeclRefExpr>(BaseExpr) && !isa<ArraySubscriptExpr>(BaseExpr) &&
!isa<ExtVectorElementExpr>(BaseExpr))
Nate Begeman
committed
return Diag(LLoc, diag::err_ext_vector_component_access,
SourceRange(LLoc, RLoc));
Chris Lattner
committed
// FIXME: need to deal with const...
ResultType = VTy->getElementType();
Chris Lattner
committed
return Diag(LHSExp->getLocStart(), diag::err_typecheck_subscript_value,
RHSExp->getSourceRange());
Chris Lattner
committed
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)) and pointers to incomplete types. Functions are not
// objects in C99.
Chris Lattner
committed
if (!ResultType->isObjectType())
return Diag(BaseExpr->getLocStart(),
diag::err_typecheck_subscript_not_object,
BaseExpr->getType().getAsString(), BaseExpr->getSourceRange());
Chris Lattner
committed
return new ArraySubscriptExpr(LHSExp, RHSExp, ResultType, RLoc);
Chris Lattner
committed
}
QualType Sema::
Nate Begeman
committed
CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc,
IdentifierInfo &CompName, SourceLocation CompLoc) {
Nate Begeman
committed
const ExtVectorType *vecType = baseType->getAsExtVectorType();
// This flag determines whether or not the component is to be treated as a
// special name, or a regular GLSL-style component access.
bool SpecialComponent = false;
// The vector accessor can't exceed the number of elements.
const char *compStr = CompName.getName();
if (strlen(compStr) > vecType->getNumElements()) {
Nate Begeman
committed
Diag(OpLoc, diag::err_ext_vector_component_exceeds_length,
baseType.getAsString(), SourceRange(CompLoc));
return QualType();
}
// Check that we've found one of the special components, or that the component
// names must come from the same set.
if (!strcmp(compStr, "hi") || !strcmp(compStr, "lo") ||
!strcmp(compStr, "e") || !strcmp(compStr, "o")) {
SpecialComponent = true;
} else 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);
}
if (!SpecialComponent && *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.
Nate Begeman
committed
Diag(OpLoc, diag::err_ext_vector_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 (!SpecialComponent && *compStr) {
// We didn't get to the end of the string. This means a component accessor
// exceeds the number of elements in the vector.
Nate Begeman
committed
Diag(OpLoc, diag::err_ext_vector_component_exceeds_length,
baseType.getAsString(), SourceRange(CompLoc));
return QualType();
}
// If we have a special component name, verify that the current vector length
// is an even number, since all special component names return exactly half
// the elements.
if (SpecialComponent && (vecType->getNumElements() & 1U)) {
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.
// vec4.hi, vec4.lo, vec4.e, and vec4.o all return vec2.
unsigned CompSize = SpecialComponent ? vecType->getNumElements() / 2
: strlen(CompName.getName());
if (CompSize == 1)
return vecType->getElementType();
Nate Begeman
committed
QualType VT = Context.getExtVectorType(vecType->getElementType(), CompSize);
Nate Begeman
committed
// diagostics look bad. We want extended vector types to appear built-in.
for (unsigned i = 0, E = ExtVectorDecls.size(); i != E; ++i) {
if (ExtVectorDecls[i]->getUnderlyingType() == VT)
return Context.getTypedefType(ExtVectorDecls[i]);
}
return VT; // should never get here (a typedef type should always be found).
/// constructSetterName - Return the setter name for the given
/// identifier, i.e. "set" + Name where the initial character of Name
/// has been capitalized.
// FIXME: Merge with same routine in Parser. But where should this
// live?
static IdentifierInfo *constructSetterName(IdentifierTable &Idents,
const IdentifierInfo *Name) {
unsigned N = Name->getLength();
char *SelectorName = new char[3 + N];
memcpy(SelectorName, "set", 3);
memcpy(&SelectorName[3], Name->getName(), N);
SelectorName[3] = toupper(SelectorName[3]);
IdentifierInfo *Setter =
&Idents.get(SelectorName, &SelectorName[3 + N]);
delete[] SelectorName;
return Setter;
}
Chris Lattner
committed
Action::ExprResult Sema::
ActOnMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
Chris Lattner
committed
tok::TokenKind OpKind, SourceLocation MemberLoc,
IdentifierInfo &Member) {
Expr *BaseExpr = static_cast<Expr *>(Base);
assert(BaseExpr && "no record expression");
// Perform default conversions.
DefaultFunctionArrayConversion(BaseExpr);
QualType BaseType = BaseExpr->getType();
assert(!BaseType.isNull() && "no type for member expression");
// Get the type being accessed in BaseType. If this is an arrow, the BaseExpr
// must have pointer type, and the accessed type is the pointee.
if (const PointerType *PT = BaseType->getAsPointerType())
return Diag(MemberLoc, diag::err_typecheck_member_reference_arrow,
BaseType.getAsString(), BaseExpr->getSourceRange());
// Handle field access to simple records. This also handles access to fields
// of the ObjC 'id' struct.
if (const RecordType *RTy = BaseType->getAsRecordType()) {
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.
FieldDecl *MemberDecl = RDecl->getMember(&Member);
if (!MemberDecl)
return Diag(MemberLoc, diag::err_typecheck_no_member, Member.getName(),
BaseExpr->getSourceRange());
// Figure out the type of the member; see C99 6.5.2.3p3
// FIXME: Handle address space modifiers
QualType MemberType = MemberDecl->getType();
unsigned combinedQualifiers =
MemberType.getCVRQualifiers() | BaseType.getCVRQualifiers();
MemberType = MemberType.getQualifiedType(combinedQualifiers);
return new MemberExpr(BaseExpr, OpKind == tok::arrow, MemberDecl,
MemberLoc, MemberType);
Chris Lattner
committed
// Handle access to Objective-C instance variables, such as "Obj->ivar" and
// (*Obj).ivar.
if (const ObjCInterfaceType *IFTy = BaseType->getAsObjCInterfaceType()) {
if (ObjCIvarDecl *IV = IFTy->getDecl()->lookupInstanceVariable(&Member))
return new ObjCIvarRefExpr(IV, IV->getType(), MemberLoc, BaseExpr,
return Diag(MemberLoc, diag::err_typecheck_member_reference_ivar,
IFTy->getDecl()->getName(), Member.getName(),
BaseExpr->getSourceRange());
Chris Lattner
committed
// Handle Objective-C property access, which is "Obj.property" where Obj is a
// pointer to a (potentially qualified) interface type.
const PointerType *PTy;
const ObjCInterfaceType *IFTy;
if (OpKind == tok::period && (PTy = BaseType->getAsPointerType()) &&
(IFTy = PTy->getPointeeType()->getAsObjCInterfaceType())) {
ObjCInterfaceDecl *IFace = IFTy->getDecl();
// Search for a declared property first.
Chris Lattner
committed
if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(&Member))
return new ObjCPropertyRefExpr(PD, PD->getType(), MemberLoc, BaseExpr);
// Check protocols on qualified interfaces.
for (ObjCInterfaceType::qual_iterator I = IFTy->qual_begin(),
E = IFTy->qual_end(); I != E; ++I)
if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(&Member))
return new ObjCPropertyRefExpr(PD, PD->getType(), MemberLoc, BaseExpr);
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// If that failed, look for an "implicit" property by seeing if the nullary
// selector is implemented.
// FIXME: The logic for looking up nullary and unary selectors should be
// shared with the code in ActOnInstanceMessage.
Selector Sel = PP.getSelectorTable().getNullarySelector(&Member);
ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel);
// If this reference is in an @implementation, check for 'private' methods.
if (!Getter)
if (ObjCMethodDecl *CurMeth = getCurMethodDecl())
if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
if (ObjCImplementationDecl *ImpDecl =
ObjCImplementations[ClassDecl->getIdentifier()])
Getter = ImpDecl->getInstanceMethod(Sel);
if (Getter) {
// If we found a getter then this may be a valid dot-reference, we
// need to also look for the matching setter.
IdentifierInfo *SetterName = constructSetterName(PP.getIdentifierTable(),
&Member);
Selector SetterSel = PP.getSelectorTable().getUnarySelector(SetterName);
ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel);
if (!Setter) {
if (ObjCMethodDecl *CurMeth = getCurMethodDecl())
if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
if (ObjCImplementationDecl *ImpDecl =
ObjCImplementations[ClassDecl->getIdentifier()])
Setter = ImpDecl->getInstanceMethod(SetterSel);
}
// FIXME: There are some issues here. First, we are not
// diagnosing accesses to read-only properties because we do not