2006-11-10 13:03:26 +08:00
|
|
|
//===--- SemaExpr.cpp - Semantic Analysis for Expressions -----------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-30 03:59:25 +08:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2006-11-10 13:03:26 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements semantic analysis for expressions.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "Sema.h"
|
2006-11-10 14:20:45 +08:00
|
|
|
#include "clang/AST/ASTContext.h"
|
2008-08-11 13:35:13 +08:00
|
|
|
#include "clang/AST/DeclObjC.h"
|
2008-04-08 12:40:51 +08:00
|
|
|
#include "clang/AST/ExprCXX.h"
|
2008-05-30 05:12:08 +08:00
|
|
|
#include "clang/AST/ExprObjC.h"
|
2006-11-10 13:03:26 +08:00
|
|
|
#include "clang/Lex/Preprocessor.h"
|
2007-03-10 07:16:33 +08:00
|
|
|
#include "clang/Lex/LiteralSupport.h"
|
2008-08-11 11:45:03 +08:00
|
|
|
#include "clang/Basic/Diagnostic.h"
|
2007-03-14 04:29:44 +08:00
|
|
|
#include "clang/Basic/SourceManager.h"
|
2006-11-10 13:03:26 +08:00
|
|
|
#include "clang/Basic/TargetInfo.h"
|
2008-09-04 02:15:37 +08:00
|
|
|
#include "clang/Parse/DeclSpec.h"
|
2008-10-27 07:43:26 +08:00
|
|
|
#include "clang/Parse/Designator.h"
|
2008-09-04 02:15:37 +08:00
|
|
|
#include "clang/Parse/Scope.h"
|
2006-11-10 13:03:26 +08:00
|
|
|
using namespace clang;
|
|
|
|
|
2008-07-26 05:10:04 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// 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 (Ty->isFunctionType())
|
|
|
|
ImpCastExprToType(E, Context.getPointerType(Ty));
|
2008-07-26 05:33:13 +08:00
|
|
|
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).
|
2008-09-11 12:25:59 +08:00
|
|
|
//
|
|
|
|
// 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)
|
2008-07-26 05:33:13 +08:00
|
|
|
ImpCastExprToType(E, Context.getArrayDecayedType(Ty));
|
|
|
|
}
|
2008-07-26 05:10:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// 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 (Ty->isPromotableIntegerType()) // C99 6.3.1.1p2
|
|
|
|
ImpCastExprToType(Expr, Context.IntTy);
|
|
|
|
else
|
|
|
|
DefaultFunctionArrayConversion(Expr);
|
|
|
|
|
|
|
|
return Expr;
|
|
|
|
}
|
|
|
|
|
2008-07-26 06:25:12 +08:00
|
|
|
/// 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);
|
|
|
|
}
|
|
|
|
|
2008-07-26 05:10:04 +08:00
|
|
|
/// 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);
|
|
|
|
}
|
Implement support for operator overloading using candidate operator
functions for built-in operators, e.g., the builtin
bool operator==(int const*, int const*)
can be used for the expression "x1 == x2" given:
struct X {
operator int const*();
} x1, x2;
The scheme for handling these built-in operators is relatively simple:
for each candidate required by the standard, create a special kind of
candidate function for the built-in. If overload resolution picks the
built-in operator, we perform the appropriate conversions on the
arguments and then let the normal built-in operator take care of it.
There may be some optimization opportunity left: if we can reduce the
number of built-in operator overloads we generate, overload resolution
for these cases will go faster. However, one must be careful when
doing this: GCC generates too few operator overloads in our little
test program, and fails to compile it because none of the overloads it
generates match.
Note that we only support operator overload for non-member binary
operators at the moment. The other operators will follow.
As part of this change, ImplicitCastExpr can now be an lvalue.
llvm-svn: 59148
2008-11-13 01:17:38 +08:00
|
|
|
|
2008-07-26 05:10:04 +08:00
|
|
|
// For conversion purposes, we ignore any qualifiers.
|
|
|
|
// For example, "const float" and "float" are equivalent.
|
2008-07-27 06:17:49 +08:00
|
|
|
QualType lhs =
|
|
|
|
Context.getCanonicalType(lhsExpr->getType()).getUnqualifiedType();
|
|
|
|
QualType rhs =
|
|
|
|
Context.getCanonicalType(rhsExpr->getType()).getUnqualifiedType();
|
Implement support for operator overloading using candidate operator
functions for built-in operators, e.g., the builtin
bool operator==(int const*, int const*)
can be used for the expression "x1 == x2" given:
struct X {
operator int const*();
} x1, x2;
The scheme for handling these built-in operators is relatively simple:
for each candidate required by the standard, create a special kind of
candidate function for the built-in. If overload resolution picks the
built-in operator, we perform the appropriate conversions on the
arguments and then let the normal built-in operator take care of it.
There may be some optimization opportunity left: if we can reduce the
number of built-in operator overloads we generate, overload resolution
for these cases will go faster. However, one must be careful when
doing this: GCC generates too few operator overloads in our little
test program, and fails to compile it because none of the overloads it
generates match.
Note that we only support operator overload for non-member binary
operators at the moment. The other operators will follow.
As part of this change, ImplicitCastExpr can now be an lvalue.
llvm-svn: 59148
2008-11-13 01:17:38 +08:00
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
|
|
|
QualType destType = UsualArithmeticConversionsType(lhs, rhs);
|
|
|
|
if (!isCompAssign) {
|
|
|
|
ImpCastExprToType(lhsExpr, destType);
|
|
|
|
ImpCastExprToType(rhsExpr, destType);
|
|
|
|
}
|
|
|
|
return destType;
|
|
|
|
}
|
|
|
|
|
|
|
|
QualType Sema::UsualArithmeticConversionsType(QualType lhs, QualType rhs) {
|
|
|
|
// Perform the usual unary conversions. We do this early so that
|
|
|
|
// integral promotions to "int" can allow us to exit early, in the
|
|
|
|
// lhs == rhs check. Also, for conversion purposes, we ignore any
|
|
|
|
// qualifiers. For example, "const float" and "float" are
|
|
|
|
// equivalent.
|
2008-11-14 04:12:29 +08:00
|
|
|
if (lhs->isPromotableIntegerType()) lhs = Context.IntTy;
|
|
|
|
else lhs = lhs.getUnqualifiedType();
|
|
|
|
if (rhs->isPromotableIntegerType()) rhs = Context.IntTy;
|
|
|
|
else rhs = rhs.getUnqualifiedType();
|
Implement support for operator overloading using candidate operator
functions for built-in operators, e.g., the builtin
bool operator==(int const*, int const*)
can be used for the expression "x1 == x2" given:
struct X {
operator int const*();
} x1, x2;
The scheme for handling these built-in operators is relatively simple:
for each candidate required by the standard, create a special kind of
candidate function for the built-in. If overload resolution picks the
built-in operator, we perform the appropriate conversions on the
arguments and then let the normal built-in operator take care of it.
There may be some optimization opportunity left: if we can reduce the
number of built-in operator overloads we generate, overload resolution
for these cases will go faster. However, one must be careful when
doing this: GCC generates too few operator overloads in our little
test program, and fails to compile it because none of the overloads it
generates match.
Note that we only support operator overload for non-member binary
operators at the moment. The other operators will follow.
As part of this change, ImplicitCastExpr can now be an lvalue.
llvm-svn: 59148
2008-11-13 01:17:38 +08:00
|
|
|
|
2008-07-26 05:10:04 +08:00
|
|
|
// 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.
|
|
|
|
return lhs;
|
|
|
|
}
|
|
|
|
if (lhs->isIntegerType() || lhs->isComplexIntegerType()) {
|
|
|
|
// convert the lhs to the rhs complex type.
|
|
|
|
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);
|
|
|
|
} else if (result < 0) { // The right side is bigger, convert lhs.
|
|
|
|
lhs = Context.getFloatingTypeOfSizeWithinDomain(rhs, 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".
|
|
|
|
return rhs;
|
|
|
|
} else { // handle "_Complex double, double".
|
|
|
|
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.
|
2008-12-11 07:30:05 +08:00
|
|
|
if (rhs->isIntegerType()) {
|
2008-07-26 05:10:04 +08:00
|
|
|
// convert rhs to the lhs floating point type.
|
|
|
|
return lhs;
|
|
|
|
}
|
2008-12-11 07:30:05 +08:00
|
|
|
if (rhs->isComplexIntegerType()) {
|
|
|
|
// convert rhs to the complex floating point type.
|
|
|
|
return Context.getComplexType(lhs);
|
|
|
|
}
|
|
|
|
if (lhs->isIntegerType()) {
|
2008-07-26 05:10:04 +08:00
|
|
|
// convert lhs to the rhs floating point type.
|
|
|
|
return rhs;
|
|
|
|
}
|
2008-12-11 07:30:05 +08:00
|
|
|
if (lhs->isComplexIntegerType()) {
|
|
|
|
// convert lhs to the complex floating point type.
|
|
|
|
return Context.getComplexType(rhs);
|
|
|
|
}
|
2008-07-26 05:10:04 +08:00
|
|
|
// 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
|
|
|
|
return lhs;
|
|
|
|
}
|
|
|
|
if (result < 0) { // convert the lhs
|
|
|
|
return rhs;
|
|
|
|
}
|
Implement support for operator overloading using candidate operator
functions for built-in operators, e.g., the builtin
bool operator==(int const*, int const*)
can be used for the expression "x1 == x2" given:
struct X {
operator int const*();
} x1, x2;
The scheme for handling these built-in operators is relatively simple:
for each candidate required by the standard, create a special kind of
candidate function for the built-in. If overload resolution picks the
built-in operator, we perform the appropriate conversions on the
arguments and then let the normal built-in operator take care of it.
There may be some optimization opportunity left: if we can reduce the
number of built-in operator overloads we generate, overload resolution
for these cases will go faster. However, one must be careful when
doing this: GCC generates too few operator overloads in our little
test program, and fails to compile it because none of the overloads it
generates match.
Note that we only support operator overload for non-member binary
operators at the moment. The other operators will follow.
As part of this change, ImplicitCastExpr can now be an lvalue.
llvm-svn: 59148
2008-11-13 01:17:38 +08:00
|
|
|
assert(0 && "Sema::UsualArithmeticConversionsType(): illegal float comparison");
|
2008-07-26 05:10:04 +08:00
|
|
|
}
|
|
|
|
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
|
|
|
|
return lhs;
|
|
|
|
}
|
|
|
|
return rhs;
|
|
|
|
} else if (lhsComplexInt && rhs->isIntegerType()) {
|
|
|
|
// convert the rhs to the lhs complex type.
|
|
|
|
return lhs;
|
|
|
|
} else if (rhsComplexInt && lhs->isIntegerType()) {
|
|
|
|
// convert the lhs to the rhs complex type.
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
return destType;
|
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Semantic Analysis for various Expression Types
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
|
2007-09-16 11:34:24 +08:00
|
|
|
/// ActOnStringLiteral - The specified tokens were lexed as pasted string
|
2006-11-10 13:03:26 +08: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 11:34:24 +08:00
|
|
|
Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) {
|
2006-11-10 13:03:26 +08:00
|
|
|
assert(NumStringToks && "Must have at least one string!");
|
|
|
|
|
2007-03-14 06:37:02 +08:00
|
|
|
StringLiteralParser Literal(StringToks, NumStringToks, PP, Context.Target);
|
|
|
|
if (Literal.hadError)
|
|
|
|
return ExprResult(true);
|
2006-11-10 13:03:26 +08:00
|
|
|
|
2007-06-16 07:05:46 +08:00
|
|
|
llvm::SmallVector<SourceLocation, 4> StringTokLocs;
|
2006-11-10 13:03:26 +08:00
|
|
|
for (unsigned i = 0; i != NumStringToks; ++i)
|
|
|
|
StringTokLocs.push_back(StringToks[i].getLocation());
|
2008-02-11 08:02:17 +08:00
|
|
|
|
|
|
|
// Verify that pascal strings aren't too large.
|
2007-10-15 10:50:23 +08:00
|
|
|
if (Literal.Pascal && Literal.GetStringLength() > 256)
|
2008-11-19 13:08:23 +08:00
|
|
|
return Diag(StringToks[0].getLocation(), diag::err_pascal_string_too_long)
|
|
|
|
<< SourceRange(StringToks[0].getLocation(),
|
|
|
|
StringToks[NumStringToks-1].getLocation());
|
2007-03-24 06:27:02 +08:00
|
|
|
|
2008-02-11 08:02:17 +08:00
|
|
|
QualType StrTy = Context.CharTy;
|
2008-08-10 01:20:01 +08:00
|
|
|
if (Literal.AnyWide) StrTy = Context.getWCharType();
|
2008-02-11 08:02:17 +08:00
|
|
|
if (Literal.Pascal) StrTy = Context.UnsignedCharTy;
|
2008-09-12 08:47:35 +08:00
|
|
|
|
|
|
|
// A C++ string literal has a const-qualified element type (C++ 2.13.4p1).
|
|
|
|
if (getLangOptions().CPlusPlus)
|
|
|
|
StrTy.addConst();
|
2008-02-11 08:02:17 +08:00
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
2006-11-10 13:03:26 +08:00
|
|
|
// Pass &StringTokLocs[0], StringTokLocs.size() to factory!
|
2007-03-14 06:37:02 +08:00
|
|
|
return new StringLiteral(Literal.GetString(), Literal.GetStringLength(),
|
2008-02-11 08:02:17 +08:00
|
|
|
Literal.AnyWide, StrTy,
|
2007-10-15 10:50:23 +08:00
|
|
|
StringToks[0].getLocation(),
|
2007-05-18 05:49:33 +08:00
|
|
|
StringToks[NumStringToks-1].getLocation());
|
2006-11-10 13:03:26 +08:00
|
|
|
}
|
|
|
|
|
2008-10-20 13:16:36 +08:00
|
|
|
/// ShouldSnapshotBlockValueReference - Return true if a reference inside of
|
|
|
|
/// CurBlock to VD should cause it to be snapshotted (as we do for auto
|
|
|
|
/// variables defined outside the block) or false if this is not needed (e.g.
|
|
|
|
/// for values inside the block or for globals).
|
|
|
|
///
|
|
|
|
/// FIXME: This will create BlockDeclRefExprs for global variables,
|
|
|
|
/// function references, etc which is suboptimal :) and breaks
|
|
|
|
/// things like "integer constant expression" tests.
|
|
|
|
static bool ShouldSnapshotBlockValueReference(BlockSemaInfo *CurBlock,
|
|
|
|
ValueDecl *VD) {
|
|
|
|
// If the value is defined inside the block, we couldn't snapshot it even if
|
|
|
|
// we wanted to.
|
|
|
|
if (CurBlock->TheDecl == VD->getDeclContext())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// If this is an enum constant or function, it is constant, don't snapshot.
|
|
|
|
if (isa<EnumConstantDecl>(VD) || isa<FunctionDecl>(VD))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// If this is a reference to an extern, static, or global variable, no need to
|
|
|
|
// snapshot it.
|
|
|
|
// FIXME: What about 'const' variables in C++?
|
|
|
|
if (const VarDecl *Var = dyn_cast<VarDecl>(VD))
|
|
|
|
return Var->hasLocalStorage();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2007-09-16 02:49:24 +08:00
|
|
|
/// ActOnIdentifierExpr - The parser read an identifier in expression context,
|
2006-11-20 14:49:47 +08:00
|
|
|
/// validate it per-C99 6.5.1. HasTrailingLParen indicates whether this
|
2008-03-20 07:46:26 +08:00
|
|
|
/// identifier is used in a function call context.
|
2008-11-09 01:17:31 +08:00
|
|
|
/// LookupCtx is only used for a C++ qualified-id (foo::bar) to indicate the
|
|
|
|
/// class or namespace that the identifier must be a member of.
|
2007-09-16 02:49:24 +08:00
|
|
|
Sema::ExprResult Sema::ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
|
2006-11-20 14:49:47 +08:00
|
|
|
IdentifierInfo &II,
|
2008-11-09 00:45:02 +08:00
|
|
|
bool HasTrailingLParen,
|
|
|
|
const CXXScopeSpec *SS) {
|
2008-11-18 23:03:34 +08:00
|
|
|
return ActOnDeclarationNameExpr(S, Loc, &II, HasTrailingLParen, SS);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ActOnDeclarationNameExpr - The parser has read some kind of name
|
|
|
|
/// (e.g., a C++ id-expression (C++ [expr.prim]p1)). This routine
|
|
|
|
/// performs lookup on that name and returns an expression that refers
|
|
|
|
/// to that name. This routine isn't directly called from the parser,
|
|
|
|
/// because the parser doesn't know about DeclarationName. Rather,
|
|
|
|
/// this routine is called by ActOnIdentifierExpr,
|
|
|
|
/// ActOnOperatorFunctionIdExpr, and ActOnConversionFunctionExpr,
|
|
|
|
/// which form the DeclarationName from the corresponding syntactic
|
|
|
|
/// forms.
|
|
|
|
///
|
|
|
|
/// HasTrailingLParen indicates whether this identifier is used in a
|
|
|
|
/// function call context. LookupCtx is only used for a C++
|
|
|
|
/// qualified-id (foo::bar) to indicate the class or namespace that
|
|
|
|
/// the identifier must be a member of.
|
2008-12-06 08:22:45 +08:00
|
|
|
///
|
|
|
|
/// If ForceResolution is true, then we will attempt to resolve the
|
|
|
|
/// name even if it looks like a dependent name. This option is off by
|
|
|
|
/// default.
|
2008-11-18 23:03:34 +08:00
|
|
|
Sema::ExprResult Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
|
|
|
|
DeclarationName Name,
|
|
|
|
bool HasTrailingLParen,
|
2008-12-06 08:22:45 +08:00
|
|
|
const CXXScopeSpec *SS,
|
|
|
|
bool ForceResolution) {
|
|
|
|
if (S->getTemplateParamParent() && Name.getAsIdentifierInfo() &&
|
|
|
|
HasTrailingLParen && !SS && !ForceResolution) {
|
|
|
|
// We've seen something of the form
|
|
|
|
// identifier(
|
|
|
|
// and we are in a template, so it is likely that 's' is a
|
|
|
|
// dependent name. However, we won't know until we've parsed all
|
|
|
|
// of the call arguments. So, build a CXXDependentNameExpr node
|
|
|
|
// to represent this name. Then, if it turns out that none of the
|
|
|
|
// arguments are type-dependent, we'll force the resolution of the
|
|
|
|
// dependent name at that point.
|
|
|
|
return new CXXDependentNameExpr(Name.getAsIdentifierInfo(),
|
|
|
|
Context.DependentTy, Loc);
|
|
|
|
}
|
|
|
|
|
2008-03-31 08:36:02 +08:00
|
|
|
// Could be enum-constant, value decl, instance variable, etc.
|
2008-11-09 01:17:31 +08:00
|
|
|
Decl *D;
|
|
|
|
if (SS && !SS->isEmpty()) {
|
|
|
|
DeclContext *DC = static_cast<DeclContext*>(SS->getScopeRep());
|
|
|
|
if (DC == 0)
|
|
|
|
return true;
|
2008-11-18 23:03:34 +08:00
|
|
|
D = LookupDecl(Name, Decl::IDNS_Ordinary, S, DC);
|
2008-11-09 01:17:31 +08:00
|
|
|
} else
|
2008-11-18 23:03:34 +08:00
|
|
|
D = LookupDecl(Name, Decl::IDNS_Ordinary, S);
|
2008-12-06 08:22:45 +08:00
|
|
|
|
2008-03-31 08:36:02 +08:00
|
|
|
// If this reference is in an Objective-C method, then ivar lookup happens as
|
|
|
|
// well.
|
2008-11-18 23:03:34 +08:00
|
|
|
IdentifierInfo *II = Name.getAsIdentifierInfo();
|
|
|
|
if (II && getCurMethodDecl()) {
|
2008-04-02 07:04:06 +08:00
|
|
|
ScopedDecl *SD = dyn_cast_or_null<ScopedDecl>(D);
|
2008-03-31 08:36:02 +08:00
|
|
|
// 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.
|
2008-04-02 07:04:06 +08:00
|
|
|
if (SD == 0 || SD->isDefinedOutsideFunctionOrMethod()) {
|
2008-06-28 14:07:14 +08:00
|
|
|
ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface();
|
2008-11-18 23:03:34 +08:00
|
|
|
if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II)) {
|
2008-03-31 08:36:02 +08:00
|
|
|
// 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);
|
2008-12-19 01:29:46 +08:00
|
|
|
ObjCIvarRefExpr *MRef= new ObjCIvarRefExpr(IV, IV->getType(), Loc,
|
|
|
|
static_cast<Expr*>(SelfExpr.Val), true, true);
|
|
|
|
Context.setFieldDecl(IFace, IV, MRef);
|
|
|
|
return MRef;
|
2008-03-31 08:36:02 +08:00
|
|
|
}
|
|
|
|
}
|
2008-08-11 03:10:41 +08:00
|
|
|
// Needed to implement property "super.method" notation.
|
2008-11-20 13:35:30 +08:00
|
|
|
if (SD == 0 && II->isStr("super")) {
|
2008-06-03 07:03:37 +08:00
|
|
|
QualType T = Context.getPointerType(Context.getObjCInterfaceType(
|
2008-06-28 14:07:14 +08:00
|
|
|
getCurMethodDecl()->getClassInterface()));
|
2008-11-04 22:56:14 +08:00
|
|
|
return new ObjCSuperExpr(Loc, T);
|
2008-06-03 07:03:37 +08:00
|
|
|
}
|
2008-03-31 08:36:02 +08:00
|
|
|
}
|
2006-11-20 12:58:19 +08:00
|
|
|
if (D == 0) {
|
2007-02-13 09:51:42 +08:00
|
|
|
// Otherwise, this could be an implicitly declared function reference (legal
|
2007-01-28 16:20:04 +08:00
|
|
|
// in C90, extension in C99).
|
2008-11-18 23:03:34 +08:00
|
|
|
if (HasTrailingLParen && II &&
|
2008-03-31 08:36:02 +08:00
|
|
|
!getLangOptions().CPlusPlus) // Not in C++.
|
2008-11-18 23:03:34 +08:00
|
|
|
D = ImplicitlyDefineFunction(Loc, *II, S);
|
2007-04-03 06:35:25 +08:00
|
|
|
else {
|
2006-11-20 14:49:47 +08:00
|
|
|
// If this name wasn't predeclared and if this is not a function call,
|
|
|
|
// diagnose the problem.
|
2008-11-09 01:17:31 +08:00
|
|
|
if (SS && !SS->isEmpty())
|
2008-11-20 14:06:08 +08:00
|
|
|
return Diag(Loc, diag::err_typecheck_no_member)
|
2008-11-24 05:45:46 +08:00
|
|
|
<< Name << SS->getRange();
|
2008-11-18 23:03:34 +08:00
|
|
|
else if (Name.getNameKind() == DeclarationName::CXXOperatorName ||
|
|
|
|
Name.getNameKind() == DeclarationName::CXXConversionFunctionName)
|
2008-11-19 13:08:23 +08:00
|
|
|
return Diag(Loc, diag::err_undeclared_use) << Name.getAsString();
|
2008-11-09 01:17:31 +08:00
|
|
|
else
|
2008-11-24 05:45:46 +08:00
|
|
|
return Diag(Loc, diag::err_undeclared_var_use) << Name;
|
2007-04-03 06:35:25 +08:00
|
|
|
}
|
2006-11-20 12:58:19 +08:00
|
|
|
}
|
2008-03-31 08:36:02 +08:00
|
|
|
|
2008-12-12 00:49:14 +08:00
|
|
|
if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
|
2008-07-01 18:37:29 +08:00
|
|
|
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext)) {
|
|
|
|
if (MD->isStatic())
|
|
|
|
// "invalid use of member 'x' in static member function"
|
2008-11-19 13:08:23 +08:00
|
|
|
return Diag(Loc, diag::err_invalid_member_use_in_static_method)
|
2008-11-24 13:29:24 +08:00
|
|
|
<< FD->getDeclName();
|
2008-12-12 00:49:14 +08:00
|
|
|
if (MD->getParent() != FD->getDeclContext())
|
2008-07-01 18:37:29 +08:00
|
|
|
// "invalid use of nonstatic data member 'x'"
|
2008-11-19 13:08:23 +08:00
|
|
|
return Diag(Loc, diag::err_invalid_non_static_member_use)
|
2008-11-24 13:29:24 +08:00
|
|
|
<< FD->getDeclName();
|
2008-07-01 18:37:29 +08:00
|
|
|
|
|
|
|
if (FD->isInvalidDecl())
|
|
|
|
return true;
|
|
|
|
|
2008-10-25 05:46:40 +08:00
|
|
|
// FIXME: Handle 'mutable'.
|
|
|
|
return new DeclRefExpr(FD,
|
|
|
|
FD->getType().getWithAdditionalQualifiers(MD->getTypeQualifiers()),Loc);
|
2008-07-01 18:37:29 +08:00
|
|
|
}
|
|
|
|
|
2008-11-24 13:29:24 +08:00
|
|
|
return Diag(Loc, diag::err_invalid_non_static_member_use)
|
|
|
|
<< FD->getDeclName();
|
2008-07-01 18:37:29 +08:00
|
|
|
}
|
2007-04-04 07:13:13 +08:00
|
|
|
if (isa<TypedefDecl>(D))
|
2008-11-24 13:29:24 +08:00
|
|
|
return Diag(Loc, diag::err_unexpected_typedef) << Name;
|
2008-01-08 03:49:32 +08:00
|
|
|
if (isa<ObjCInterfaceDecl>(D))
|
2008-11-24 13:29:24 +08:00
|
|
|
return Diag(Loc, diag::err_unexpected_interface) << Name;
|
2008-04-27 21:50:30 +08:00
|
|
|
if (isa<NamespaceDecl>(D))
|
2008-11-24 13:29:24 +08:00
|
|
|
return Diag(Loc, diag::err_unexpected_namespace) << Name;
|
2007-03-24 06:27:02 +08:00
|
|
|
|
2008-09-06 06:11:13 +08:00
|
|
|
// Make the DeclRefExpr or BlockDeclRefExpr for the decl.
|
2008-10-22 00:13:35 +08:00
|
|
|
if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(D))
|
|
|
|
return new DeclRefExpr(Ovl, Context.OverloadTy, Loc);
|
|
|
|
|
2008-09-06 06:11:13 +08:00
|
|
|
ValueDecl *VD = cast<ValueDecl>(D);
|
|
|
|
|
|
|
|
// check if referencing an identifier with __attribute__((deprecated)).
|
|
|
|
if (VD->getAttr<DeprecatedAttr>())
|
2008-11-24 13:29:24 +08:00
|
|
|
Diag(Loc, diag::warn_deprecated) << VD->getDeclName();
|
2008-12-11 07:01:14 +08:00
|
|
|
|
|
|
|
if (VarDecl *Var = dyn_cast<VarDecl>(VD)) {
|
|
|
|
if (Var->isDeclaredInCondition() && Var->getType()->isScalarType()) {
|
|
|
|
Scope *CheckS = S;
|
|
|
|
while (CheckS) {
|
|
|
|
if (CheckS->isWithinElse() &&
|
|
|
|
CheckS->getControlParent()->isDeclScope(Var)) {
|
|
|
|
if (Var->getType()->isBooleanType())
|
|
|
|
Diag(Loc, diag::warn_value_always_false) << Var->getDeclName();
|
|
|
|
else
|
|
|
|
Diag(Loc, diag::warn_value_always_zero) << Var->getDeclName();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Move up one more control parent to check again.
|
|
|
|
CheckS = CheckS->getControlParent();
|
|
|
|
if (CheckS)
|
|
|
|
CheckS = CheckS->getParent();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-09-06 06:11:13 +08:00
|
|
|
|
|
|
|
// Only create DeclRefExpr's for valid Decl's.
|
|
|
|
if (VD->isInvalidDecl())
|
|
|
|
return true;
|
2008-10-20 13:16:36 +08:00
|
|
|
|
|
|
|
// If the identifier reference is inside a block, and it refers to a value
|
|
|
|
// that is outside the block, create a BlockDeclRefExpr instead of a
|
|
|
|
// DeclRefExpr. This ensures the value is treated as a copy-in snapshot when
|
|
|
|
// the block is formed.
|
2008-09-06 06:11:13 +08:00
|
|
|
//
|
2008-10-20 13:16:36 +08:00
|
|
|
// We do not do this for things like enum constants, global variables, etc,
|
|
|
|
// as they do not get snapshotted.
|
|
|
|
//
|
|
|
|
if (CurBlock && ShouldSnapshotBlockValueReference(CurBlock, VD)) {
|
2008-10-10 09:28:17 +08:00
|
|
|
// The BlocksAttr indicates the variable is bound by-reference.
|
|
|
|
if (VD->getAttr<BlocksAttr>())
|
2008-10-28 08:22:11 +08:00
|
|
|
return new BlockDeclRefExpr(VD, VD->getType().getNonReferenceType(),
|
|
|
|
Loc, true);
|
2008-10-10 09:28:17 +08:00
|
|
|
|
|
|
|
// Variable will be bound by-copy, make it const within the closure.
|
|
|
|
VD->getType().addConst();
|
2008-10-28 08:22:11 +08:00
|
|
|
return new BlockDeclRefExpr(VD, VD->getType().getNonReferenceType(),
|
|
|
|
Loc, false);
|
2008-10-10 09:28:17 +08:00
|
|
|
}
|
|
|
|
// If this reference is not in a block or if the referenced variable is
|
|
|
|
// within the block, create a normal DeclRefExpr.
|
2008-12-06 07:32:09 +08:00
|
|
|
|
|
|
|
bool TypeDependent = false;
|
2008-12-11 04:57:37 +08:00
|
|
|
bool ValueDependent = false;
|
|
|
|
if (getLangOptions().CPlusPlus) {
|
|
|
|
// C++ [temp.dep.expr]p3:
|
|
|
|
// An id-expression is type-dependent if it contains:
|
|
|
|
// - an identifier that was declared with a dependent type,
|
|
|
|
if (VD->getType()->isDependentType())
|
|
|
|
TypeDependent = true;
|
|
|
|
// - FIXME: a template-id that is dependent,
|
|
|
|
// - a conversion-function-id that specifies a dependent type,
|
|
|
|
else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName &&
|
|
|
|
Name.getCXXNameType()->isDependentType())
|
|
|
|
TypeDependent = true;
|
|
|
|
// - a nested-name-specifier that contains a class-name that
|
|
|
|
// names a dependent type.
|
|
|
|
else if (SS && !SS->isEmpty()) {
|
|
|
|
for (DeclContext *DC = static_cast<DeclContext*>(SS->getScopeRep());
|
|
|
|
DC; DC = DC->getParent()) {
|
|
|
|
// FIXME: could stop early at namespace scope.
|
|
|
|
if (DC->isCXXRecord()) {
|
|
|
|
CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);
|
|
|
|
if (Context.getTypeDeclType(Record)->isDependentType()) {
|
|
|
|
TypeDependent = true;
|
|
|
|
break;
|
|
|
|
}
|
2008-12-06 07:32:09 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-11 04:57:37 +08:00
|
|
|
// C++ [temp.dep.constexpr]p2:
|
|
|
|
//
|
|
|
|
// An identifier is value-dependent if it is:
|
|
|
|
// - a name declared with a dependent type,
|
|
|
|
if (TypeDependent)
|
|
|
|
ValueDependent = true;
|
|
|
|
// - the name of a non-type template parameter,
|
|
|
|
else if (isa<NonTypeTemplateParmDecl>(VD))
|
|
|
|
ValueDependent = true;
|
|
|
|
// - a constant with integral or enumeration type and is
|
|
|
|
// initialized with an expression that is value-dependent
|
|
|
|
// (FIXME!).
|
|
|
|
}
|
2008-12-06 07:32:09 +08:00
|
|
|
|
|
|
|
return new DeclRefExpr(VD, VD->getType().getNonReferenceType(), Loc,
|
|
|
|
TypeDependent, ValueDependent);
|
2006-11-20 12:58:19 +08:00
|
|
|
}
|
2006-11-10 13:29:30 +08:00
|
|
|
|
2008-08-10 09:53:14 +08:00
|
|
|
Sema::ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc,
|
2007-07-21 13:21:51 +08:00
|
|
|
tok::TokenKind Kind) {
|
2008-08-10 09:53:14 +08:00
|
|
|
PredefinedExpr::IdentType IT;
|
2007-07-21 13:21:51 +08:00
|
|
|
|
2006-11-10 13:29:30 +08:00
|
|
|
switch (Kind) {
|
2008-01-13 02:39:25 +08:00
|
|
|
default: assert(0 && "Unknown simple primary expr!");
|
2008-08-10 09:53:14 +08:00
|
|
|
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;
|
2006-11-10 13:29:30 +08:00
|
|
|
}
|
2008-01-13 02:39:25 +08:00
|
|
|
|
2008-01-12 16:14:25 +08:00
|
|
|
// Pre-defined identifiers are of type char[x], where x is the length of the
|
|
|
|
// string.
|
2008-01-13 03:32:28 +08:00
|
|
|
unsigned Length;
|
2008-12-05 07:50:19 +08:00
|
|
|
if (FunctionDecl *FD = getCurFunctionDecl())
|
|
|
|
Length = FD->getIdentifier()->getLength();
|
2008-12-12 13:05:20 +08:00
|
|
|
else if (ObjCMethodDecl *MD = getCurMethodDecl())
|
|
|
|
Length = MD->getSynthesizedMethodSize();
|
|
|
|
else {
|
|
|
|
Diag(Loc, diag::ext_predef_outside_function);
|
|
|
|
// __PRETTY_FUNCTION__ -> "top level", the others produce an empty string.
|
|
|
|
Length = IT == PredefinedExpr::PrettyFunction ? strlen("top level") : 0;
|
|
|
|
}
|
|
|
|
|
2008-01-13 02:39:25 +08:00
|
|
|
|
2008-01-13 03:32:28 +08:00
|
|
|
llvm::APInt LengthI(32, Length + 1);
|
2008-01-13 02:39:25 +08:00
|
|
|
QualType ResTy = Context.CharTy.getQualifiedType(QualType::Const);
|
2008-01-13 03:32:28 +08:00
|
|
|
ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0);
|
2008-08-10 09:53:14 +08:00
|
|
|
return new PredefinedExpr(Loc, ResTy, IT);
|
2006-11-10 13:29:30 +08:00
|
|
|
}
|
|
|
|
|
2007-09-16 11:34:24 +08:00
|
|
|
Sema::ExprResult Sema::ActOnCharacterConstant(const Token &Tok) {
|
2007-06-16 07:05:46 +08:00
|
|
|
llvm::SmallString<16> CharBuffer;
|
2007-04-27 04:39:23 +08: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);
|
2008-03-01 16:32:21 +08:00
|
|
|
|
|
|
|
QualType type = getLangOptions().CPlusPlus ? Context.CharTy : Context.IntTy;
|
|
|
|
|
2008-06-08 06:35:38 +08:00
|
|
|
return new CharacterLiteral(Literal.getValue(), Literal.isWide(), type,
|
|
|
|
Tok.getLocation());
|
2007-04-27 04:39:23 +08:00
|
|
|
}
|
|
|
|
|
2007-09-16 11:34:24 +08:00
|
|
|
Action::ExprResult Sema::ActOnNumericConstant(const Token &Tok) {
|
2007-03-14 04:29:44 +08: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) {
|
2008-04-02 12:24:33 +08:00
|
|
|
const char *Ty = PP.getSourceManager().getCharacterData(Tok.getLocation());
|
2007-05-21 09:08:44 +08:00
|
|
|
|
2008-03-06 02:54:05 +08:00
|
|
|
unsigned IntSize =static_cast<unsigned>(Context.getTypeSize(Context.IntTy));
|
2008-04-02 12:24:33 +08:00
|
|
|
return ExprResult(new IntegerLiteral(llvm::APInt(IntSize, *Ty-'0'),
|
2007-06-16 07:05:46 +08:00
|
|
|
Context.IntTy,
|
2007-05-17 09:16:00 +08:00
|
|
|
Tok.getLocation()));
|
2007-03-14 04:29:44 +08:00
|
|
|
}
|
2007-06-16 07:05:46 +08:00
|
|
|
llvm::SmallString<512> IntegerBuffer;
|
2008-10-01 04:53:45 +08:00
|
|
|
// Add padding so that NumericLiteralParser can overread by one character.
|
|
|
|
IntegerBuffer.resize(Tok.getLength()+1);
|
2007-03-06 09:09:46 +08:00
|
|
|
const char *ThisTokBegin = &IntegerBuffer[0];
|
|
|
|
|
2007-05-21 09:08:44 +08:00
|
|
|
// Get the spelling of the token, which eliminates trigraphs, etc.
|
2007-03-06 09:09:46 +08:00
|
|
|
unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin);
|
2008-10-01 04:51:14 +08:00
|
|
|
|
2007-03-10 07:16:33 +08:00
|
|
|
NumericLiteralParser Literal(ThisTokBegin, ThisTokBegin+ActualLength,
|
2007-03-13 07:22:38 +08:00
|
|
|
Tok.getLocation(), PP);
|
2007-03-14 04:29:44 +08:00
|
|
|
if (Literal.hadError)
|
|
|
|
return ExprResult(true);
|
2007-05-21 09:08:44 +08:00
|
|
|
|
2007-08-26 11:42:43 +08:00
|
|
|
Expr *Res;
|
|
|
|
|
|
|
|
if (Literal.isFloatingLiteral()) {
|
2007-09-23 02:29:59 +08:00
|
|
|
QualType Ty;
|
2008-07-01 02:32:54 +08:00
|
|
|
if (Literal.isFloat)
|
2007-09-23 02:29:59 +08:00
|
|
|
Ty = Context.FloatTy;
|
2008-07-01 02:32:54 +08:00
|
|
|
else if (!Literal.isLong)
|
2007-09-23 02:29:59 +08:00
|
|
|
Ty = Context.DoubleTy;
|
2008-07-01 02:32:54 +08:00
|
|
|
else
|
2008-03-08 16:52:55 +08:00
|
|
|
Ty = Context.LongDoubleTy;
|
2008-07-01 02:32:54 +08:00
|
|
|
|
|
|
|
const llvm::fltSemantics &Format = Context.getFloatTypeSemantics(Ty);
|
|
|
|
|
2007-11-29 08:56:49 +08:00
|
|
|
// isExact will be set by GetFloatValue().
|
|
|
|
bool isExact = false;
|
2008-07-01 02:32:54 +08:00
|
|
|
Res = new FloatingLiteral(Literal.GetFloatValue(Format, &isExact), &isExact,
|
2007-11-29 08:56:49 +08:00
|
|
|
Ty, Tok.getLocation());
|
|
|
|
|
2007-08-26 11:42:43 +08:00
|
|
|
} else if (!Literal.isIntegerLiteral()) {
|
|
|
|
return ExprResult(true);
|
|
|
|
} else {
|
2008-04-02 12:24:33 +08:00
|
|
|
QualType Ty;
|
2007-05-21 09:08:44 +08:00
|
|
|
|
2007-08-30 06:00:19 +08:00
|
|
|
// long long is a C99 feature.
|
|
|
|
if (!getLangOptions().C99 && !getLangOptions().CPlusPlus0x &&
|
2007-08-30 06:13:52 +08:00
|
|
|
Literal.isLongLong)
|
2007-08-30 06:00:19 +08:00
|
|
|
Diag(Tok.getLocation(), diag::ext_longlong);
|
|
|
|
|
2007-05-21 09:08:44 +08:00
|
|
|
// Get the value in the widest-possible width.
|
2008-03-06 02:54:05 +08:00
|
|
|
llvm::APInt ResultVal(Context.Target.getIntMaxTWidth(), 0);
|
2007-05-21 09:08:44 +08: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);
|
2008-04-02 12:24:33 +08:00
|
|
|
Ty = Context.UnsignedLongLongTy;
|
|
|
|
assert(Context.getTypeSize(Ty) == ResultVal.getBitWidth() &&
|
2008-03-06 02:54:05 +08:00
|
|
|
"long long is not intmax_t?");
|
2007-03-06 09:09:46 +08:00
|
|
|
} else {
|
2007-05-21 09:08:44 +08: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.
|
2008-05-09 13:59:00 +08:00
|
|
|
unsigned Width = 0;
|
2007-08-24 05:58:08 +08:00
|
|
|
if (!Literal.isLong && !Literal.isLongLong) {
|
|
|
|
// Are int/unsigned possibilities?
|
2008-05-09 13:59:00 +08:00
|
|
|
unsigned IntSize = Context.Target.getIntWidth();
|
|
|
|
|
2007-05-21 09:08:44 +08: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)
|
2008-04-02 12:24:33 +08:00
|
|
|
Ty = Context.IntTy;
|
2007-05-21 09:08:44 +08:00
|
|
|
else if (AllowUnsigned)
|
2008-04-02 12:24:33 +08:00
|
|
|
Ty = Context.UnsignedIntTy;
|
2008-05-09 13:59:00 +08:00
|
|
|
Width = IntSize;
|
2007-05-21 09:08:44 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Are long/unsigned long possibilities?
|
2008-04-02 12:24:33 +08:00
|
|
|
if (Ty.isNull() && !Literal.isLongLong) {
|
2008-05-09 13:59:00 +08:00
|
|
|
unsigned LongSize = Context.Target.getLongWidth();
|
2007-05-21 09:08:44 +08: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)
|
2008-04-02 12:24:33 +08:00
|
|
|
Ty = Context.LongTy;
|
2007-05-21 09:08:44 +08:00
|
|
|
else if (AllowUnsigned)
|
2008-04-02 12:24:33 +08:00
|
|
|
Ty = Context.UnsignedLongTy;
|
2008-05-09 13:59:00 +08:00
|
|
|
Width = LongSize;
|
2007-05-21 09:08:44 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Finally, check long long if needed.
|
2008-04-02 12:24:33 +08:00
|
|
|
if (Ty.isNull()) {
|
2008-05-09 13:59:00 +08:00
|
|
|
unsigned LongLongSize = Context.Target.getLongLongWidth();
|
2007-05-21 09:08:44 +08: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)
|
2008-04-02 12:24:33 +08:00
|
|
|
Ty = Context.LongLongTy;
|
2007-05-21 09:08:44 +08:00
|
|
|
else if (AllowUnsigned)
|
2008-04-02 12:24:33 +08:00
|
|
|
Ty = Context.UnsignedLongLongTy;
|
2008-05-09 13:59:00 +08:00
|
|
|
Width = LongLongSize;
|
2007-05-21 09:08:44 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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.
|
2008-04-02 12:24:33 +08:00
|
|
|
if (Ty.isNull()) {
|
2007-05-21 09:08:44 +08:00
|
|
|
Diag(Tok.getLocation(), diag::warn_integer_too_large_for_signed);
|
2008-04-02 12:24:33 +08:00
|
|
|
Ty = Context.UnsignedLongLongTy;
|
2008-05-09 13:59:00 +08:00
|
|
|
Width = Context.Target.getLongLongWidth();
|
2007-05-21 09:08:44 +08:00
|
|
|
}
|
2008-05-09 13:59:00 +08:00
|
|
|
|
|
|
|
if (ResultVal.getBitWidth() != Width)
|
|
|
|
ResultVal.trunc(Width);
|
2007-03-07 09:21:37 +08:00
|
|
|
}
|
2007-05-21 09:08:44 +08:00
|
|
|
|
2008-04-02 12:24:33 +08:00
|
|
|
Res = new IntegerLiteral(ResultVal, Ty, Tok.getLocation());
|
2007-03-06 09:09:46 +08:00
|
|
|
}
|
2007-08-26 11:42:43 +08: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 13:29:30 +08:00
|
|
|
}
|
|
|
|
|
2007-09-16 11:34:24 +08:00
|
|
|
Action::ExprResult Sema::ActOnParenExpr(SourceLocation L, SourceLocation R,
|
2006-11-10 13:29:30 +08:00
|
|
|
ExprTy *Val) {
|
2008-04-02 12:24:33 +08:00
|
|
|
Expr *E = (Expr *)Val;
|
|
|
|
assert((E != 0) && "ActOnParenExpr() missing expr");
|
|
|
|
return new ParenExpr(L, R, E);
|
2006-11-10 13:29:30 +08:00
|
|
|
}
|
|
|
|
|
2007-06-05 06:22:31 +08:00
|
|
|
/// The UsualUnaryConversions() function is *not* called by this routine.
|
2007-05-17 03:47:19 +08:00
|
|
|
/// See C99 6.3.2.1p[2-4] for more details.
|
2008-11-12 01:56:53 +08:00
|
|
|
bool Sema::CheckSizeOfAlignOfOperand(QualType exprType,
|
|
|
|
SourceLocation OpLoc,
|
|
|
|
const SourceRange &ExprRange,
|
|
|
|
bool isSizeof) {
|
2007-05-15 10:32:35 +08:00
|
|
|
// C99 6.5.3.4p1:
|
|
|
|
if (isa<FunctionType>(exprType) && isSizeof)
|
|
|
|
// alignof(function) is allowed.
|
2008-11-19 13:08:23 +08:00
|
|
|
Diag(OpLoc, diag::ext_sizeof_function_type) << ExprRange;
|
2007-05-15 10:32:35 +08:00
|
|
|
else if (exprType->isVoidType())
|
2008-11-19 13:08:23 +08:00
|
|
|
Diag(OpLoc, diag::ext_sizeof_void_type)
|
|
|
|
<< (isSizeof ? "sizeof" : "__alignof") << ExprRange;
|
|
|
|
else if (exprType->isIncompleteType())
|
|
|
|
return Diag(OpLoc, isSizeof ? diag::err_sizeof_incomplete_type :
|
|
|
|
diag::err_alignof_incomplete_type)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< exprType << ExprRange;
|
2008-11-12 01:56:53 +08:00
|
|
|
|
|
|
|
return false;
|
2007-05-15 10:32:35 +08:00
|
|
|
}
|
|
|
|
|
2008-11-12 01:56:53 +08:00
|
|
|
/// ActOnSizeOfAlignOfExpr - Handle @c sizeof(type) and @c sizeof @c expr and
|
|
|
|
/// the same for @c alignof and @c __alignof
|
|
|
|
/// Note that the ArgRange is invalid if isType is false.
|
|
|
|
Action::ExprResult
|
|
|
|
Sema::ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType,
|
|
|
|
void *TyOrEx, const SourceRange &ArgRange) {
|
2006-11-20 12:34:45 +08:00
|
|
|
// If error parsing type, ignore.
|
2008-11-12 01:56:53 +08:00
|
|
|
if (TyOrEx == 0) return true;
|
2007-05-15 10:32:35 +08:00
|
|
|
|
2008-11-12 01:56:53 +08:00
|
|
|
QualType ArgTy;
|
|
|
|
SourceRange Range;
|
|
|
|
if (isType) {
|
|
|
|
ArgTy = QualType::getFromOpaquePtr(TyOrEx);
|
|
|
|
Range = ArgRange;
|
|
|
|
} else {
|
|
|
|
// Get the end location.
|
|
|
|
Expr *ArgEx = (Expr *)TyOrEx;
|
|
|
|
Range = ArgEx->getSourceRange();
|
|
|
|
ArgTy = ArgEx->getType();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify that the operand is valid.
|
|
|
|
if (CheckSizeOfAlignOfOperand(ArgTy, OpLoc, Range, isSizeof))
|
2007-05-15 10:32:35 +08:00
|
|
|
return true;
|
2008-11-12 01:56:53 +08:00
|
|
|
|
|
|
|
// C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
|
|
|
|
return new SizeOfAlignOfExpr(isSizeof, isType, TyOrEx, Context.getSizeType(),
|
|
|
|
OpLoc, Range.getEnd());
|
2006-11-10 13:29:30 +08:00
|
|
|
}
|
|
|
|
|
2007-08-25 05:41:10 +08:00
|
|
|
QualType Sema::CheckRealImagOperand(Expr *&V, SourceLocation Loc) {
|
2007-08-25 05:16:53 +08:00
|
|
|
DefaultFunctionArrayConversion(V);
|
|
|
|
|
2007-08-26 13:39:26 +08:00
|
|
|
// These operators return the element type of a complex type.
|
2007-08-25 05:16:53 +08:00
|
|
|
if (const ComplexType *CT = V->getType()->getAsComplexType())
|
|
|
|
return CT->getElementType();
|
2007-08-26 13:39:26 +08:00
|
|
|
|
|
|
|
// Otherwise they pass through real integer and floating point types here.
|
|
|
|
if (V->getType()->isArithmeticType())
|
|
|
|
return V->getType();
|
|
|
|
|
|
|
|
// Reject anything else.
|
2008-11-24 14:25:27 +08:00
|
|
|
Diag(Loc, diag::err_realimag_invalid_type) << V->getType();
|
2007-08-26 13:39:26 +08:00
|
|
|
return QualType();
|
2007-08-25 05:16:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-11-10 13:29:30 +08:00
|
|
|
|
2008-11-19 23:42:04 +08:00
|
|
|
Action::ExprResult Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
|
2006-11-10 13:29:30 +08:00
|
|
|
tok::TokenKind Kind,
|
|
|
|
ExprTy *Input) {
|
2008-11-19 23:42:04 +08:00
|
|
|
Expr *Arg = (Expr *)Input;
|
|
|
|
|
2006-11-10 13:29:30 +08:00
|
|
|
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;
|
|
|
|
}
|
2008-11-19 23:42:04 +08:00
|
|
|
|
|
|
|
if (getLangOptions().CPlusPlus &&
|
|
|
|
(Arg->getType()->isRecordType() || Arg->getType()->isEnumeralType())) {
|
|
|
|
// Which overloaded operator?
|
|
|
|
OverloadedOperatorKind OverOp =
|
|
|
|
(Opc == UnaryOperator::PostInc)? OO_PlusPlus : OO_MinusMinus;
|
|
|
|
|
|
|
|
// C++ [over.inc]p1:
|
|
|
|
//
|
|
|
|
// [...] If the function is a member function with one
|
|
|
|
// parameter (which shall be of type int) or a non-member
|
|
|
|
// function with two parameters (the second of which shall be
|
|
|
|
// of type int), it defines the postfix increment operator ++
|
|
|
|
// for objects of that type. When the postfix increment is
|
|
|
|
// called as a result of using the ++ operator, the int
|
|
|
|
// argument will have value zero.
|
|
|
|
Expr *Args[2] = {
|
|
|
|
Arg,
|
|
|
|
new IntegerLiteral(llvm::APInt(Context.Target.getIntWidth(), 0,
|
|
|
|
/*isSigned=*/true),
|
|
|
|
Context.IntTy, SourceLocation())
|
|
|
|
};
|
|
|
|
|
|
|
|
// Build the candidate set for overloading
|
|
|
|
OverloadCandidateSet CandidateSet;
|
|
|
|
AddOperatorCandidates(OverOp, S, Args, 2, CandidateSet);
|
|
|
|
|
|
|
|
// Perform overload resolution.
|
|
|
|
OverloadCandidateSet::iterator Best;
|
|
|
|
switch (BestViableFunction(CandidateSet, Best)) {
|
|
|
|
case OR_Success: {
|
|
|
|
// We found a built-in operator or an overloaded operator.
|
|
|
|
FunctionDecl *FnDecl = Best->Function;
|
|
|
|
|
|
|
|
if (FnDecl) {
|
|
|
|
// We matched an overloaded operator. Build a call to that
|
|
|
|
// operator.
|
|
|
|
|
|
|
|
// Convert the arguments.
|
|
|
|
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
|
|
|
|
if (PerformObjectArgumentInitialization(Arg, Method))
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
// Convert the arguments.
|
|
|
|
if (PerformCopyInitialization(Arg,
|
|
|
|
FnDecl->getParamDecl(0)->getType(),
|
|
|
|
"passing"))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Determine the result type
|
|
|
|
QualType ResultTy
|
|
|
|
= FnDecl->getType()->getAsFunctionType()->getResultType();
|
|
|
|
ResultTy = ResultTy.getNonReferenceType();
|
|
|
|
|
|
|
|
// Build the actual expression node.
|
|
|
|
Expr *FnExpr = new DeclRefExpr(FnDecl, FnDecl->getType(),
|
|
|
|
SourceLocation());
|
|
|
|
UsualUnaryConversions(FnExpr);
|
|
|
|
|
|
|
|
return new CXXOperatorCallExpr(FnExpr, Args, 2, ResultTy, OpLoc);
|
|
|
|
} else {
|
|
|
|
// We matched a built-in operator. Convert the arguments, then
|
|
|
|
// break out so that we will build the appropriate built-in
|
|
|
|
// operator node.
|
|
|
|
if (PerformCopyInitialization(Arg, Best->BuiltinTypes.ParamTypes[0],
|
|
|
|
"passing"))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
case OR_No_Viable_Function:
|
|
|
|
// No viable function; fall through to handling this as a
|
|
|
|
// built-in operator, which will produce an error message for us.
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OR_Ambiguous:
|
|
|
|
Diag(OpLoc, diag::err_ovl_ambiguous_oper)
|
|
|
|
<< UnaryOperator::getOpcodeStr(Opc)
|
|
|
|
<< Arg->getSourceRange();
|
|
|
|
PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Either we found no viable overloaded operator or we matched a
|
|
|
|
// built-in operator. In either case, fall through to trying to
|
|
|
|
// build a built-in operation.
|
|
|
|
}
|
|
|
|
|
|
|
|
QualType result = CheckIncrementDecrementOperand(Arg, OpLoc);
|
2007-05-07 08:24:15 +08:00
|
|
|
if (result.isNull())
|
|
|
|
return true;
|
2008-11-19 23:42:04 +08:00
|
|
|
return new UnaryOperator(Arg, Opc, result, OpLoc);
|
2006-11-10 13:29:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Action::ExprResult Sema::
|
2008-11-20 01:17:41 +08:00
|
|
|
ActOnArraySubscriptExpr(Scope *S, ExprTy *Base, SourceLocation LLoc,
|
2006-11-10 13:29:30 +08:00
|
|
|
ExprTy *Idx, SourceLocation RLoc) {
|
2007-07-16 07:59:53 +08:00
|
|
|
Expr *LHSExp = static_cast<Expr*>(Base), *RHSExp = static_cast<Expr*>(Idx);
|
2007-07-16 08:14:47 +08:00
|
|
|
|
2008-11-20 01:17:41 +08:00
|
|
|
if (getLangOptions().CPlusPlus &&
|
2008-12-16 06:34:21 +08:00
|
|
|
(LHSExp->getType()->isRecordType() ||
|
|
|
|
LHSExp->getType()->isEnumeralType() ||
|
|
|
|
RHSExp->getType()->isRecordType() ||
|
|
|
|
RHSExp->getType()->isEnumeralType())) {
|
2008-11-20 01:17:41 +08:00
|
|
|
// Add the appropriate overloaded operators (C++ [over.match.oper])
|
|
|
|
// to the candidate set.
|
|
|
|
OverloadCandidateSet CandidateSet;
|
|
|
|
Expr *Args[2] = { LHSExp, RHSExp };
|
|
|
|
AddOperatorCandidates(OO_Subscript, S, Args, 2, CandidateSet);
|
|
|
|
|
|
|
|
// Perform overload resolution.
|
|
|
|
OverloadCandidateSet::iterator Best;
|
|
|
|
switch (BestViableFunction(CandidateSet, Best)) {
|
|
|
|
case OR_Success: {
|
|
|
|
// We found a built-in operator or an overloaded operator.
|
|
|
|
FunctionDecl *FnDecl = Best->Function;
|
|
|
|
|
|
|
|
if (FnDecl) {
|
|
|
|
// We matched an overloaded operator. Build a call to that
|
|
|
|
// operator.
|
|
|
|
|
|
|
|
// Convert the arguments.
|
|
|
|
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
|
|
|
|
if (PerformObjectArgumentInitialization(LHSExp, Method) ||
|
|
|
|
PerformCopyInitialization(RHSExp,
|
|
|
|
FnDecl->getParamDecl(0)->getType(),
|
|
|
|
"passing"))
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
// Convert the arguments.
|
|
|
|
if (PerformCopyInitialization(LHSExp,
|
|
|
|
FnDecl->getParamDecl(0)->getType(),
|
|
|
|
"passing") ||
|
|
|
|
PerformCopyInitialization(RHSExp,
|
|
|
|
FnDecl->getParamDecl(1)->getType(),
|
|
|
|
"passing"))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Determine the result type
|
|
|
|
QualType ResultTy
|
|
|
|
= FnDecl->getType()->getAsFunctionType()->getResultType();
|
|
|
|
ResultTy = ResultTy.getNonReferenceType();
|
|
|
|
|
|
|
|
// Build the actual expression node.
|
|
|
|
Expr *FnExpr = new DeclRefExpr(FnDecl, FnDecl->getType(),
|
|
|
|
SourceLocation());
|
|
|
|
UsualUnaryConversions(FnExpr);
|
|
|
|
|
|
|
|
return new CXXOperatorCallExpr(FnExpr, Args, 2, ResultTy, LLoc);
|
|
|
|
} else {
|
|
|
|
// We matched a built-in operator. Convert the arguments, then
|
|
|
|
// break out so that we will build the appropriate built-in
|
|
|
|
// operator node.
|
|
|
|
if (PerformCopyInitialization(LHSExp, Best->BuiltinTypes.ParamTypes[0],
|
|
|
|
"passing") ||
|
|
|
|
PerformCopyInitialization(RHSExp, Best->BuiltinTypes.ParamTypes[1],
|
|
|
|
"passing"))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
case OR_No_Viable_Function:
|
|
|
|
// No viable function; fall through to handling this as a
|
|
|
|
// built-in operator, which will produce an error message for us.
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OR_Ambiguous:
|
|
|
|
Diag(LLoc, diag::err_ovl_ambiguous_oper)
|
|
|
|
<< "[]"
|
|
|
|
<< LHSExp->getSourceRange() << RHSExp->getSourceRange();
|
|
|
|
PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Either we found no viable overloaded operator or we matched a
|
|
|
|
// built-in operator. In either case, fall through to trying to
|
|
|
|
// build a built-in operation.
|
|
|
|
}
|
|
|
|
|
2007-07-16 08:14:47 +08:00
|
|
|
// Perform default conversions.
|
|
|
|
DefaultFunctionArrayConversion(LHSExp);
|
|
|
|
DefaultFunctionArrayConversion(RHSExp);
|
2007-07-16 07:59:53 +08:00
|
|
|
|
2007-07-16 08:14:47 +08:00
|
|
|
QualType LHSTy = LHSExp->getType(), RHSTy = RHSExp->getType();
|
2007-03-24 06:27:02 +08:00
|
|
|
|
2007-03-29 05:49:40 +08:00
|
|
|
// C99 6.5.2.1p2: the expression e1[e2] is by definition precisely equivalent
|
2007-08-31 01:45:32 +08:00
|
|
|
// to the expression *((e1)+(e2)). This means the array "Base" may actually be
|
2007-03-24 06:27:02 +08:00
|
|
|
// in the subscript position. As a result, we need to derive the array base
|
|
|
|
// and index from the expression types.
|
2007-07-16 08:14:47 +08:00
|
|
|
Expr *BaseExpr, *IndexExpr;
|
|
|
|
QualType ResultType;
|
2007-08-01 00:53:04 +08:00
|
|
|
if (const PointerType *PTy = LHSTy->getAsPointerType()) {
|
2007-07-16 08:14:47 +08:00
|
|
|
BaseExpr = LHSExp;
|
|
|
|
IndexExpr = RHSExp;
|
|
|
|
// FIXME: need to deal with const...
|
|
|
|
ResultType = PTy->getPointeeType();
|
2007-08-01 00:53:04 +08:00
|
|
|
} else if (const PointerType *PTy = RHSTy->getAsPointerType()) {
|
2007-07-16 08:23:25 +08:00
|
|
|
// Handle the uncommon case of "123[Ptr]".
|
2007-07-16 08:14:47 +08:00
|
|
|
BaseExpr = RHSExp;
|
|
|
|
IndexExpr = LHSExp;
|
|
|
|
// FIXME: need to deal with const...
|
|
|
|
ResultType = PTy->getPointeeType();
|
2007-08-01 03:29:30 +08:00
|
|
|
} else if (const VectorType *VTy = LHSTy->getAsVectorType()) {
|
|
|
|
BaseExpr = LHSExp; // vectors: V[123]
|
2007-07-16 08:14:47 +08:00
|
|
|
IndexExpr = RHSExp;
|
2007-08-04 06:40:33 +08:00
|
|
|
|
|
|
|
// Component access limited to variables (reject vec4.rg[1]).
|
2008-05-09 14:41:27 +08:00
|
|
|
if (!isa<DeclRefExpr>(BaseExpr) && !isa<ArraySubscriptExpr>(BaseExpr) &&
|
|
|
|
!isa<ExtVectorElementExpr>(BaseExpr))
|
2008-11-19 13:08:23 +08:00
|
|
|
return Diag(LLoc, diag::err_ext_vector_component_access)
|
|
|
|
<< SourceRange(LLoc, RLoc);
|
2007-07-16 08:14:47 +08:00
|
|
|
// FIXME: need to deal with const...
|
|
|
|
ResultType = VTy->getElementType();
|
2007-06-09 11:47:53 +08:00
|
|
|
} else {
|
2008-11-19 13:08:23 +08:00
|
|
|
return Diag(LHSExp->getLocStart(), diag::err_typecheck_subscript_value)
|
|
|
|
<< RHSExp->getSourceRange();
|
2007-06-09 11:47:53 +08:00
|
|
|
}
|
2007-03-29 05:49:40 +08:00
|
|
|
// C99 6.5.2.1p1
|
2007-07-16 08:14:47 +08:00
|
|
|
if (!IndexExpr->getType()->isIntegerType())
|
2008-11-19 13:08:23 +08:00
|
|
|
return Diag(IndexExpr->getLocStart(), diag::err_typecheck_subscript)
|
|
|
|
<< IndexExpr->getSourceRange();
|
2007-07-16 08:14:47 +08:00
|
|
|
|
|
|
|
// 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.
|
2008-04-02 14:59:01 +08:00
|
|
|
// void (*)(int)) and pointers to incomplete types. Functions are not
|
|
|
|
// objects in C99.
|
2007-07-16 08:14:47 +08:00
|
|
|
if (!ResultType->isObjectType())
|
|
|
|
return Diag(BaseExpr->getLocStart(),
|
2008-11-19 13:08:23 +08:00
|
|
|
diag::err_typecheck_subscript_not_object)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< BaseExpr->getType() << BaseExpr->getSourceRange();
|
2007-07-11 02:23:31 +08:00
|
|
|
|
2007-07-16 08:14:47 +08:00
|
|
|
return new ArraySubscriptExpr(LHSExp, RHSExp, ResultType, RLoc);
|
2006-11-10 13:29:30 +08:00
|
|
|
}
|
|
|
|
|
2007-07-28 06:15:19 +08:00
|
|
|
QualType Sema::
|
2008-04-19 07:10:10 +08:00
|
|
|
CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc,
|
2007-07-28 06:15:19 +08:00
|
|
|
IdentifierInfo &CompName, SourceLocation CompLoc) {
|
2008-04-19 07:10:10 +08:00
|
|
|
const ExtVectorType *vecType = baseType->getAsExtVectorType();
|
2008-05-09 14:41:27 +08:00
|
|
|
|
|
|
|
// 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;
|
2007-07-28 06:15:19 +08:00
|
|
|
|
|
|
|
// The vector accessor can't exceed the number of elements.
|
|
|
|
const char *compStr = CompName.getName();
|
|
|
|
if (strlen(compStr) > vecType->getNumElements()) {
|
2008-11-19 13:08:23 +08:00
|
|
|
Diag(OpLoc, diag::err_ext_vector_component_exceeds_length)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< baseType << SourceRange(CompLoc);
|
2007-07-28 06:15:19 +08:00
|
|
|
return QualType();
|
|
|
|
}
|
2008-05-09 14:41:27 +08:00
|
|
|
|
|
|
|
// 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) {
|
2007-08-03 06:33:49 +08:00
|
|
|
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-28 06:15:19 +08:00
|
|
|
|
2008-05-09 14:41:27 +08:00
|
|
|
if (!SpecialComponent && *compStr) {
|
2007-07-28 06:15:19 +08:00
|
|
|
// 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.
|
2008-11-19 13:08:23 +08:00
|
|
|
Diag(OpLoc, diag::err_ext_vector_component_name_illegal)
|
|
|
|
<< std::string(compStr,compStr+1) << SourceRange(CompLoc);
|
2007-07-28 06:15:19 +08:00
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
// Each component accessor can't exceed the vector type.
|
|
|
|
compStr = CompName.getName();
|
|
|
|
while (*compStr) {
|
|
|
|
if (vecType->isAccessorWithinNumElements(*compStr))
|
|
|
|
compStr++;
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
2008-05-09 14:41:27 +08:00
|
|
|
if (!SpecialComponent && *compStr) {
|
2007-07-28 06:15:19 +08:00
|
|
|
// We didn't get to the end of the string. This means a component accessor
|
|
|
|
// exceeds the number of elements in the vector.
|
2008-11-19 13:08:23 +08:00
|
|
|
Diag(OpLoc, diag::err_ext_vector_component_exceeds_length)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< baseType << SourceRange(CompLoc);
|
2007-07-28 06:15:19 +08:00
|
|
|
return QualType();
|
|
|
|
}
|
2008-05-09 14:41:27 +08:00
|
|
|
|
|
|
|
// 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)) {
|
2008-11-19 13:08:23 +08:00
|
|
|
Diag(OpLoc, diag::err_ext_vector_component_requires_even)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< baseType << SourceRange(CompLoc);
|
2008-05-09 14:41:27 +08:00
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2007-07-28 06:15:19 +08:00
|
|
|
// 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.
|
2008-05-09 14:41:27 +08:00
|
|
|
// vec4.hi, vec4.lo, vec4.e, and vec4.o all return vec2.
|
|
|
|
unsigned CompSize = SpecialComponent ? vecType->getNumElements() / 2
|
2008-11-19 16:23:25 +08:00
|
|
|
: CompName.getLength();
|
2007-07-28 06:15:19 +08:00
|
|
|
if (CompSize == 1)
|
|
|
|
return vecType->getElementType();
|
2007-07-30 00:33:31 +08:00
|
|
|
|
2008-04-19 07:10:10 +08:00
|
|
|
QualType VT = Context.getExtVectorType(vecType->getElementType(), CompSize);
|
2007-07-30 00:33:31 +08:00
|
|
|
// Now look up the TypeDefDecl from the vector type. Without this,
|
2008-04-19 07:10:10 +08:00
|
|
|
// 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]);
|
2007-07-30 00:33:31 +08:00
|
|
|
}
|
|
|
|
return VT; // should never get here (a typedef type should always be found).
|
2007-07-28 06:15:19 +08:00
|
|
|
}
|
|
|
|
|
2008-11-23 04:25:50 +08:00
|
|
|
/// 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) {
|
|
|
|
llvm::SmallString<100> SelectorName;
|
|
|
|
SelectorName = "set";
|
|
|
|
SelectorName.append(Name->getName(), Name->getName()+Name->getLength());
|
|
|
|
SelectorName[3] = toupper(SelectorName[3]);
|
|
|
|
return &Idents.get(&SelectorName[0], &SelectorName[SelectorName.size()]);
|
|
|
|
}
|
|
|
|
|
2006-11-10 13:29:30 +08:00
|
|
|
Action::ExprResult Sema::
|
2007-09-16 11:34:24 +08:00
|
|
|
ActOnMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
|
2006-11-10 13:29:30 +08:00
|
|
|
tok::TokenKind OpKind, SourceLocation MemberLoc,
|
|
|
|
IdentifierInfo &Member) {
|
2007-07-26 11:11:44 +08:00
|
|
|
Expr *BaseExpr = static_cast<Expr *>(Base);
|
|
|
|
assert(BaseExpr && "no record expression");
|
2007-12-17 05:42:28 +08:00
|
|
|
|
|
|
|
// Perform default conversions.
|
|
|
|
DefaultFunctionArrayConversion(BaseExpr);
|
2007-04-01 09:41:35 +08:00
|
|
|
|
2007-07-26 11:11:44 +08:00
|
|
|
QualType BaseType = BaseExpr->getType();
|
|
|
|
assert(!BaseType.isNull() && "no type for member expression");
|
2007-04-01 09:41:35 +08:00
|
|
|
|
2008-07-21 12:36:39 +08:00
|
|
|
// 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.
|
2007-03-24 06:27:02 +08:00
|
|
|
if (OpKind == tok::arrow) {
|
2007-08-01 00:53:04 +08:00
|
|
|
if (const PointerType *PT = BaseType->getAsPointerType())
|
2007-07-26 11:11:44 +08:00
|
|
|
BaseType = PT->getPointeeType();
|
2008-11-21 00:27:02 +08:00
|
|
|
else if (getLangOptions().CPlusPlus && BaseType->isRecordType())
|
|
|
|
return BuildOverloadedArrowExpr(BaseExpr, OpLoc, MemberLoc, Member);
|
2007-07-26 11:11:44 +08:00
|
|
|
else
|
2008-11-19 13:08:23 +08:00
|
|
|
return Diag(MemberLoc, diag::err_typecheck_member_reference_arrow)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< BaseType << BaseExpr->getSourceRange();
|
2007-03-24 06:27:02 +08:00
|
|
|
}
|
2008-07-21 12:28:12 +08:00
|
|
|
|
2008-07-21 12:36:39 +08:00
|
|
|
// Handle field access to simple records. This also handles access to fields
|
|
|
|
// of the ObjC 'id' struct.
|
2007-08-01 03:29:30 +08:00
|
|
|
if (const RecordType *RTy = BaseType->getAsRecordType()) {
|
2007-07-26 11:11:44 +08:00
|
|
|
RecordDecl *RDecl = RTy->getDecl();
|
|
|
|
if (RTy->isIncompleteType())
|
2008-11-19 13:08:23 +08:00
|
|
|
return Diag(OpLoc, diag::err_typecheck_incomplete_tag)
|
2008-11-24 13:29:24 +08:00
|
|
|
<< RDecl->getDeclName() << BaseExpr->getSourceRange();
|
2007-07-26 11:11:44 +08:00
|
|
|
// The record definition is complete, now make sure the member is valid.
|
2008-12-12 00:49:14 +08:00
|
|
|
// FIXME: Qualified name lookup for C++ is a bit more complicated
|
|
|
|
// than this.
|
|
|
|
DeclContext::lookup_result Lookup = RDecl->lookup(Context, &Member);
|
|
|
|
if (Lookup.first == Lookup.second) {
|
2008-11-19 13:08:23 +08:00
|
|
|
return Diag(MemberLoc, diag::err_typecheck_no_member)
|
2008-11-19 16:23:25 +08:00
|
|
|
<< &Member << BaseExpr->getSourceRange();
|
2008-12-12 00:49:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
FieldDecl *MemberDecl = dyn_cast<FieldDecl>(*Lookup.first);
|
|
|
|
if (!MemberDecl) {
|
|
|
|
unsigned DiagID = PP.getDiagnostics().getCustomDiagID(Diagnostic::Error,
|
|
|
|
"Clang only supports references to members");
|
|
|
|
return Diag(MemberLoc, DiagID);
|
|
|
|
}
|
2008-02-07 06:48:16 +08:00
|
|
|
|
|
|
|
// Figure out the type of the member; see C99 6.5.2.3p3
|
2008-02-07 13:24:51 +08:00
|
|
|
// FIXME: Handle address space modifiers
|
2008-02-07 06:48:16 +08:00
|
|
|
QualType MemberType = MemberDecl->getType();
|
|
|
|
unsigned combinedQualifiers =
|
2008-02-21 04:55:12 +08:00
|
|
|
MemberType.getCVRQualifiers() | BaseType.getCVRQualifiers();
|
2008-12-12 00:49:14 +08:00
|
|
|
if (MemberDecl->isMutable())
|
|
|
|
combinedQualifiers &= ~QualType::Const;
|
2008-02-07 06:48:16 +08:00
|
|
|
MemberType = MemberType.getQualifiedType(combinedQualifiers);
|
|
|
|
|
2008-07-21 12:36:39 +08:00
|
|
|
return new MemberExpr(BaseExpr, OpKind == tok::arrow, MemberDecl,
|
2008-02-07 06:48:16 +08:00
|
|
|
MemberLoc, MemberType);
|
2008-07-21 12:28:12 +08:00
|
|
|
}
|
|
|
|
|
2008-07-21 12:59:05 +08:00
|
|
|
// Handle access to Objective-C instance variables, such as "Obj->ivar" and
|
|
|
|
// (*Obj).ivar.
|
2008-07-21 12:36:39 +08:00
|
|
|
if (const ObjCInterfaceType *IFTy = BaseType->getAsObjCInterfaceType()) {
|
2008-12-14 06:20:28 +08:00
|
|
|
if (ObjCIvarDecl *IV = IFTy->getDecl()->lookupInstanceVariable(&Member)) {
|
2008-12-19 01:29:46 +08:00
|
|
|
ObjCIvarRefExpr *MRef= new ObjCIvarRefExpr(IV, IV->getType(), MemberLoc,
|
|
|
|
BaseExpr,
|
|
|
|
OpKind == tok::arrow);
|
|
|
|
Context.setFieldDecl(IFTy->getDecl(), IV, MRef);
|
|
|
|
return MRef;
|
2008-12-14 06:20:28 +08:00
|
|
|
}
|
2008-11-19 13:08:23 +08:00
|
|
|
return Diag(MemberLoc, diag::err_typecheck_member_reference_ivar)
|
2008-11-24 13:29:24 +08:00
|
|
|
<< IFTy->getDecl()->getDeclName() << &Member
|
2008-11-19 13:08:23 +08:00
|
|
|
<< BaseExpr->getSourceRange();
|
2008-07-21 12:28:12 +08:00
|
|
|
}
|
|
|
|
|
2008-07-21 12:59:05 +08:00
|
|
|
// 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();
|
2008-08-30 13:35:15 +08:00
|
|
|
|
2008-09-03 09:05:41 +08:00
|
|
|
// Search for a declared property first.
|
2008-07-21 12:59:05 +08:00
|
|
|
if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(&Member))
|
|
|
|
return new ObjCPropertyRefExpr(PD, PD->getType(), MemberLoc, BaseExpr);
|
|
|
|
|
2008-09-03 09:05:41 +08:00
|
|
|
// Check protocols on qualified interfaces.
|
2008-07-21 13:20:01 +08:00
|
|
|
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);
|
2008-09-03 09:05:41 +08:00
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
2008-10-23 03:16:27 +08:00
|
|
|
// Look through local category implementations associated with the class.
|
|
|
|
if (!Getter) {
|
|
|
|
for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Getter; i++) {
|
|
|
|
if (ObjCCategoryImpls[i]->getClassInterface() == IFace)
|
|
|
|
Getter = ObjCCategoryImpls[i]->getInstanceMethod(Sel);
|
|
|
|
}
|
|
|
|
}
|
2008-09-03 09:05:41 +08:00
|
|
|
if (Getter) {
|
|
|
|
// If we found a getter then this may be a valid dot-reference, we
|
2008-11-23 04:25:50 +08:00
|
|
|
// will look for the matching setter, in case it is needed.
|
|
|
|
IdentifierInfo *SetterName = constructSetterName(PP.getIdentifierTable(),
|
|
|
|
&Member);
|
|
|
|
Selector SetterSel = PP.getSelectorTable().getUnarySelector(SetterName);
|
|
|
|
ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel);
|
|
|
|
if (!Setter) {
|
|
|
|
// If this reference is in an @implementation, also check for 'private'
|
|
|
|
// methods.
|
|
|
|
if (ObjCMethodDecl *CurMeth = getCurMethodDecl())
|
|
|
|
if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
|
|
|
|
if (ObjCImplementationDecl *ImpDecl =
|
|
|
|
ObjCImplementations[ClassDecl->getIdentifier()])
|
|
|
|
Setter = ImpDecl->getInstanceMethod(SetterSel);
|
|
|
|
}
|
|
|
|
// Look through local category implementations associated with the class.
|
|
|
|
if (!Setter) {
|
|
|
|
for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Setter; i++) {
|
|
|
|
if (ObjCCategoryImpls[i]->getClassInterface() == IFace)
|
|
|
|
Setter = ObjCCategoryImpls[i]->getInstanceMethod(SetterSel);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: we must check that the setter has property type.
|
|
|
|
return new ObjCKVCRefExpr(Getter, Getter->getResultType(), Setter,
|
2008-11-23 02:39:36 +08:00
|
|
|
MemberLoc, BaseExpr);
|
2008-09-03 09:05:41 +08:00
|
|
|
}
|
2008-12-20 01:27:57 +08:00
|
|
|
|
|
|
|
return Diag(MemberLoc, diag::err_property_not_found) <<
|
|
|
|
&Member << BaseType;
|
2007-11-13 06:29:28 +08:00
|
|
|
}
|
2008-10-21 06:53:06 +08:00
|
|
|
// Handle properties on qualified "id" protocols.
|
|
|
|
const ObjCQualifiedIdType *QIdTy;
|
|
|
|
if (OpKind == tok::period && (QIdTy = BaseType->getAsObjCQualifiedIdType())) {
|
|
|
|
// Check protocols on qualified interfaces.
|
|
|
|
for (ObjCQualifiedIdType::qual_iterator I = QIdTy->qual_begin(),
|
2008-12-10 08:21:50 +08:00
|
|
|
E = QIdTy->qual_end(); I != E; ++I) {
|
2008-10-21 06:53:06 +08:00
|
|
|
if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(&Member))
|
|
|
|
return new ObjCPropertyRefExpr(PD, PD->getType(), MemberLoc, BaseExpr);
|
2008-12-10 08:21:50 +08:00
|
|
|
// Also must look for a getter name which uses property syntax.
|
|
|
|
Selector Sel = PP.getSelectorTable().getNullarySelector(&Member);
|
|
|
|
if (ObjCMethodDecl *OMD = (*I)->getInstanceMethod(Sel)) {
|
|
|
|
return new ObjCMessageExpr(BaseExpr, Sel, OMD->getResultType(), OMD,
|
|
|
|
OpLoc, MemberLoc, NULL, 0);
|
|
|
|
}
|
|
|
|
}
|
2008-12-20 01:27:57 +08:00
|
|
|
|
|
|
|
return Diag(MemberLoc, diag::err_property_not_found) <<
|
|
|
|
&Member << BaseType;
|
2008-10-21 06:53:06 +08:00
|
|
|
}
|
2008-07-21 12:28:12 +08:00
|
|
|
// Handle 'field access' to vectors, such as 'V.xx'.
|
|
|
|
if (BaseType->isExtVectorType() && OpKind == tok::period) {
|
|
|
|
// Component access limited to variables (reject vec4.rg.g).
|
|
|
|
if (!isa<DeclRefExpr>(BaseExpr) && !isa<ArraySubscriptExpr>(BaseExpr) &&
|
|
|
|
!isa<ExtVectorElementExpr>(BaseExpr))
|
2008-11-19 13:08:23 +08:00
|
|
|
return Diag(MemberLoc, diag::err_ext_vector_component_access)
|
|
|
|
<< BaseExpr->getSourceRange();
|
2008-07-21 12:28:12 +08:00
|
|
|
QualType ret = CheckExtVectorComponent(BaseType, OpLoc, Member, MemberLoc);
|
|
|
|
if (ret.isNull())
|
|
|
|
return true;
|
|
|
|
return new ExtVectorElementExpr(ret, BaseExpr, Member, MemberLoc);
|
|
|
|
}
|
|
|
|
|
2008-11-19 13:08:23 +08:00
|
|
|
return Diag(MemberLoc, diag::err_typecheck_member_reference_struct_union)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< BaseType << BaseExpr->getSourceRange();
|
2006-11-10 13:29:30 +08:00
|
|
|
}
|
|
|
|
|
2007-09-16 11:34:24 +08:00
|
|
|
/// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
|
2006-11-10 13:29:30 +08:00
|
|
|
/// This provides the location of the left/right parens and a list of comma
|
|
|
|
/// locations.
|
|
|
|
Action::ExprResult Sema::
|
2008-12-06 08:22:45 +08:00
|
|
|
ActOnCallExpr(Scope *S, ExprTy *fn, SourceLocation LParenLoc,
|
2007-12-28 13:29:59 +08:00
|
|
|
ExprTy **args, unsigned NumArgs,
|
2006-11-10 13:29:30 +08:00
|
|
|
SourceLocation *CommaLocs, SourceLocation RParenLoc) {
|
2007-07-21 11:03:59 +08:00
|
|
|
Expr *Fn = static_cast<Expr *>(fn);
|
|
|
|
Expr **Args = reinterpret_cast<Expr**>(args);
|
|
|
|
assert(Fn && "no function call expression");
|
2008-04-08 12:40:51 +08:00
|
|
|
FunctionDecl *FDecl = NULL;
|
2008-10-22 00:13:35 +08:00
|
|
|
OverloadedFunctionDecl *Ovl = NULL;
|
|
|
|
|
2008-12-06 08:22:45 +08:00
|
|
|
// Determine whether this is a dependent call inside a C++ template,
|
|
|
|
// in which case we won't do any semantic analysis now.
|
|
|
|
bool Dependent = false;
|
|
|
|
if (Fn->isTypeDependent()) {
|
|
|
|
if (CXXDependentNameExpr *FnName = dyn_cast<CXXDependentNameExpr>(Fn)) {
|
|
|
|
if (Expr::hasAnyTypeDependentArguments(Args, NumArgs))
|
|
|
|
Dependent = true;
|
|
|
|
else {
|
|
|
|
// Resolve the CXXDependentNameExpr to an actual identifier;
|
|
|
|
// it wasn't really a dependent name after all.
|
|
|
|
ExprResult Resolved
|
|
|
|
= ActOnDeclarationNameExpr(S, FnName->getLocation(), FnName->getName(),
|
|
|
|
/*HasTrailingLParen=*/true,
|
|
|
|
/*SS=*/0,
|
|
|
|
/*ForceResolution=*/true);
|
|
|
|
if (Resolved.isInvalid)
|
|
|
|
return true;
|
|
|
|
else {
|
|
|
|
delete Fn;
|
|
|
|
Fn = (Expr *)Resolved.Val;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
Dependent = true;
|
|
|
|
} else
|
|
|
|
Dependent = Expr::hasAnyTypeDependentArguments(Args, NumArgs);
|
|
|
|
|
2008-12-06 07:32:09 +08:00
|
|
|
// FIXME: Will need to cache the results of name lookup (including
|
|
|
|
// ADL) in Fn.
|
2008-12-06 08:22:45 +08:00
|
|
|
if (Dependent)
|
2008-12-06 07:32:09 +08:00
|
|
|
return new CallExpr(Fn, Args, NumArgs, Context.DependentTy, RParenLoc);
|
|
|
|
|
2008-10-22 00:13:35 +08:00
|
|
|
// If we're directly calling a function or a set of overloaded
|
|
|
|
// functions, get the appropriate declaration.
|
|
|
|
{
|
|
|
|
DeclRefExpr *DRExpr = NULL;
|
|
|
|
if (ImplicitCastExpr *IcExpr = dyn_cast<ImplicitCastExpr>(Fn))
|
|
|
|
DRExpr = dyn_cast<DeclRefExpr>(IcExpr->getSubExpr());
|
|
|
|
else
|
|
|
|
DRExpr = dyn_cast<DeclRefExpr>(Fn);
|
|
|
|
|
|
|
|
if (DRExpr) {
|
|
|
|
FDecl = dyn_cast<FunctionDecl>(DRExpr->getDecl());
|
|
|
|
Ovl = dyn_cast<OverloadedFunctionDecl>(DRExpr->getDecl());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Ovl) {
|
2008-11-26 14:01:48 +08:00
|
|
|
FDecl = ResolveOverloadedCallFn(Fn, Ovl, LParenLoc, Args, NumArgs, CommaLocs,
|
|
|
|
RParenLoc);
|
|
|
|
if (!FDecl)
|
2008-10-22 00:13:35 +08:00
|
|
|
return true;
|
|
|
|
|
2008-11-26 14:01:48 +08:00
|
|
|
// Update Fn to refer to the actual function selected.
|
|
|
|
Expr *NewFn = new DeclRefExpr(FDecl, FDecl->getType(),
|
|
|
|
Fn->getSourceRange().getBegin());
|
|
|
|
Fn->Destroy(Context);
|
|
|
|
Fn = NewFn;
|
2008-10-22 00:13:35 +08:00
|
|
|
}
|
2008-04-08 12:40:51 +08:00
|
|
|
|
2008-11-20 05:05:33 +08:00
|
|
|
if (getLangOptions().CPlusPlus && Fn->getType()->isRecordType())
|
2008-12-06 08:22:45 +08:00
|
|
|
return BuildCallToObjectOfClassType(S, Fn, LParenLoc, Args, NumArgs,
|
2008-11-20 05:05:33 +08:00
|
|
|
CommaLocs, RParenLoc);
|
|
|
|
|
2008-04-08 12:40:51 +08:00
|
|
|
// Promote the function operand.
|
|
|
|
UsualUnaryConversions(Fn);
|
|
|
|
|
2007-12-28 13:29:59 +08:00
|
|
|
// Make the call expr early, before semantic checks. This guarantees cleanup
|
|
|
|
// of arguments and function on error.
|
2008-04-10 10:22:51 +08:00
|
|
|
llvm::OwningPtr<CallExpr> TheCall(new CallExpr(Fn, Args, NumArgs,
|
2007-12-28 13:29:59 +08:00
|
|
|
Context.BoolTy, RParenLoc));
|
2008-12-06 07:32:09 +08:00
|
|
|
|
2008-09-06 06:11:13 +08:00
|
|
|
const FunctionType *FuncT;
|
|
|
|
if (!Fn->getType()->isBlockPointerType()) {
|
|
|
|
// C99 6.5.2.2p1 - "The expression that denotes the called function shall
|
|
|
|
// have type pointer to function".
|
|
|
|
const PointerType *PT = Fn->getType()->getAsPointerType();
|
|
|
|
if (PT == 0)
|
2008-11-19 13:08:23 +08:00
|
|
|
return Diag(LParenLoc, diag::err_typecheck_call_not_function)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< Fn->getType() << Fn->getSourceRange();
|
2008-09-06 06:11:13 +08:00
|
|
|
FuncT = PT->getPointeeType()->getAsFunctionType();
|
|
|
|
} else { // This is a block call.
|
|
|
|
FuncT = Fn->getType()->getAsBlockPointerType()->getPointeeType()->
|
|
|
|
getAsFunctionType();
|
|
|
|
}
|
2007-12-28 13:29:59 +08:00
|
|
|
if (FuncT == 0)
|
2008-11-19 13:08:23 +08:00
|
|
|
return Diag(LParenLoc, diag::err_typecheck_call_not_function)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< Fn->getType() << Fn->getSourceRange();
|
2007-12-28 13:29:59 +08:00
|
|
|
|
|
|
|
// We know the result type of the call, set it.
|
2008-10-29 10:00:59 +08:00
|
|
|
TheCall->setType(FuncT->getResultType().getNonReferenceType());
|
2007-05-09 06:18:00 +08:00
|
|
|
|
2007-12-28 13:29:59 +08:00
|
|
|
if (const FunctionTypeProto *Proto = dyn_cast<FunctionTypeProto>(FuncT)) {
|
2007-05-04 05:03:48 +08:00
|
|
|
// C99 6.5.2.2p7 - the arguments are implicitly converted, as if by
|
|
|
|
// assignment, to the types of the corresponding parameter, ...
|
2007-12-28 13:29:59 +08:00
|
|
|
unsigned NumArgsInProto = Proto->getNumArgs();
|
|
|
|
unsigned NumArgsToCheck = NumArgs;
|
2007-05-04 05:03:48 +08:00
|
|
|
|
2008-04-08 12:40:51 +08:00
|
|
|
// If too few arguments are available (and we don't have default
|
|
|
|
// arguments for the remaining parameters), don't make the call.
|
|
|
|
if (NumArgs < NumArgsInProto) {
|
2008-11-22 02:44:24 +08:00
|
|
|
if (!FDecl || NumArgs < FDecl->getMinRequiredArguments())
|
|
|
|
return Diag(RParenLoc, diag::err_typecheck_call_too_few_args)
|
|
|
|
<< Fn->getType()->isBlockPointerType() << Fn->getSourceRange();
|
|
|
|
// Use default arguments for missing arguments
|
|
|
|
NumArgsToCheck = NumArgsInProto;
|
|
|
|
TheCall->setNumArgs(NumArgsInProto);
|
2008-04-08 12:40:51 +08:00
|
|
|
}
|
|
|
|
|
2007-12-28 13:29:59 +08:00
|
|
|
// If too many are passed and not variadic, error on the extras and drop
|
|
|
|
// them.
|
|
|
|
if (NumArgs > NumArgsInProto) {
|
|
|
|
if (!Proto->isVariadic()) {
|
2008-11-22 02:44:24 +08:00
|
|
|
Diag(Args[NumArgsInProto]->getLocStart(),
|
|
|
|
diag::err_typecheck_call_too_many_args)
|
|
|
|
<< Fn->getType()->isBlockPointerType() << Fn->getSourceRange()
|
2008-11-19 13:08:23 +08:00
|
|
|
<< SourceRange(Args[NumArgsInProto]->getLocStart(),
|
|
|
|
Args[NumArgs-1]->getLocEnd());
|
2007-12-28 13:29:59 +08:00
|
|
|
// This deletes the extra arguments.
|
|
|
|
TheCall->setNumArgs(NumArgsInProto);
|
2007-05-29 03:25:56 +08:00
|
|
|
}
|
2007-05-09 06:18:00 +08:00
|
|
|
NumArgsToCheck = NumArgsInProto;
|
2007-05-04 05:03:48 +08:00
|
|
|
}
|
2007-12-28 13:29:59 +08:00
|
|
|
|
2007-05-04 05:03:48 +08:00
|
|
|
// Continue to check argument types (even if we have too few/many args).
|
2007-12-28 13:29:59 +08:00
|
|
|
for (unsigned i = 0; i != NumArgsToCheck; i++) {
|
2008-01-05 02:04:52 +08:00
|
|
|
QualType ProtoArgType = Proto->getArgType(i);
|
2008-04-08 12:40:51 +08:00
|
|
|
|
|
|
|
Expr *Arg;
|
|
|
|
if (i < NumArgs)
|
|
|
|
Arg = Args[i];
|
|
|
|
else
|
|
|
|
Arg = new CXXDefaultArgExpr(FDecl->getParamDecl(i));
|
2008-01-05 02:04:52 +08:00
|
|
|
QualType ArgType = Arg->getType();
|
2007-12-28 13:29:59 +08:00
|
|
|
|
2008-10-29 08:13:59 +08:00
|
|
|
// Pass the argument.
|
|
|
|
if (PerformCopyInitialization(Arg, ProtoArgType, "passing"))
|
2008-01-05 02:04:52 +08:00
|
|
|
return true;
|
2008-10-29 08:13:59 +08:00
|
|
|
|
|
|
|
TheCall->setArg(i, Arg);
|
2007-05-04 05:03:48 +08:00
|
|
|
}
|
2007-12-28 13:29:59 +08:00
|
|
|
|
|
|
|
// If this is a variadic call, handle args passed through "...".
|
|
|
|
if (Proto->isVariadic()) {
|
2007-08-29 07:30:39 +08:00
|
|
|
// Promote the arguments (C99 6.5.2.2p7).
|
2007-12-28 13:29:59 +08:00
|
|
|
for (unsigned i = NumArgsInProto; i != NumArgs; i++) {
|
|
|
|
Expr *Arg = Args[i];
|
|
|
|
DefaultArgumentPromotion(Arg);
|
|
|
|
TheCall->setArg(i, Arg);
|
2007-08-29 07:30:39 +08:00
|
|
|
}
|
|
|
|
}
|
2007-12-28 13:29:59 +08:00
|
|
|
} else {
|
|
|
|
assert(isa<FunctionTypeNoProto>(FuncT) && "Unknown FunctionType!");
|
|
|
|
|
2007-08-29 07:30:39 +08:00
|
|
|
// Promote the arguments (C99 6.5.2.2p6).
|
2007-12-28 13:29:59 +08:00
|
|
|
for (unsigned i = 0; i != NumArgs; i++) {
|
|
|
|
Expr *Arg = Args[i];
|
|
|
|
DefaultArgumentPromotion(Arg);
|
|
|
|
TheCall->setArg(i, Arg);
|
2007-08-29 07:30:39 +08:00
|
|
|
}
|
2007-04-27 04:39:23 +08:00
|
|
|
}
|
2007-12-28 13:29:59 +08:00
|
|
|
|
2007-08-11 04:18:51 +08:00
|
|
|
// Do special checking on direct calls to functions.
|
2008-05-15 03:38:39 +08:00
|
|
|
if (FDecl)
|
|
|
|
return CheckFunctionCall(FDecl, TheCall.take());
|
2007-08-11 04:18:51 +08:00
|
|
|
|
2007-12-28 13:29:59 +08:00
|
|
|
return TheCall.take();
|
2006-11-10 13:29:30 +08:00
|
|
|
}
|
|
|
|
|
2007-07-19 09:06:55 +08:00
|
|
|
Action::ExprResult Sema::
|
2007-09-16 11:34:24 +08:00
|
|
|
ActOnCompoundLiteral(SourceLocation LParenLoc, TypeTy *Ty,
|
2007-07-20 05:32:11 +08:00
|
|
|
SourceLocation RParenLoc, ExprTy *InitExpr) {
|
2007-09-16 11:34:24 +08:00
|
|
|
assert((Ty != 0) && "ActOnCompoundLiteral(): missing type");
|
2007-07-19 09:06:55 +08:00
|
|
|
QualType literalType = QualType::getFromOpaquePtr(Ty);
|
2007-07-20 05:32:11 +08:00
|
|
|
// FIXME: put back this assert when initializers are worked out.
|
2007-09-16 11:34:24 +08:00
|
|
|
//assert((InitExpr != 0) && "ActOnCompoundLiteral(): missing expression");
|
2007-07-20 05:32:11 +08:00
|
|
|
Expr *literalExpr = static_cast<Expr*>(InitExpr);
|
2007-12-05 15:24:19 +08:00
|
|
|
|
2008-05-20 13:22:08 +08:00
|
|
|
if (literalType->isArrayType()) {
|
2008-08-04 15:31:14 +08:00
|
|
|
if (literalType->isVariableArrayType())
|
2008-11-19 13:08:23 +08:00
|
|
|
return Diag(LParenLoc, diag::err_variable_object_no_init)
|
|
|
|
<< SourceRange(LParenLoc, literalExpr->getSourceRange().getEnd());
|
2008-05-20 13:22:08 +08:00
|
|
|
} else if (literalType->isIncompleteType()) {
|
2008-11-19 13:08:23 +08:00
|
|
|
return Diag(LParenLoc, diag::err_typecheck_decl_incomplete_type)
|
2008-11-24 13:29:24 +08:00
|
|
|
<< literalType
|
2008-11-19 13:08:23 +08:00
|
|
|
<< SourceRange(LParenLoc, literalExpr->getSourceRange().getEnd());
|
2008-05-20 13:22:08 +08:00
|
|
|
}
|
|
|
|
|
2008-11-05 23:29:30 +08:00
|
|
|
if (CheckInitializerTypes(literalExpr, literalType, LParenLoc,
|
2008-11-24 13:29:24 +08:00
|
|
|
DeclarationName()))
|
2008-01-10 04:58:06 +08:00
|
|
|
return true;
|
2008-01-15 02:19:28 +08:00
|
|
|
|
2008-12-05 07:50:19 +08:00
|
|
|
bool isFileScope = getCurFunctionOrMethodDecl() == 0;
|
2008-01-15 02:19:28 +08:00
|
|
|
if (isFileScope) { // 6.5.2.5p3
|
2008-01-11 06:15:12 +08:00
|
|
|
if (CheckForConstantInitializer(literalExpr, literalType))
|
|
|
|
return true;
|
|
|
|
}
|
2008-10-27 07:35:51 +08:00
|
|
|
return new CompoundLiteralExpr(LParenLoc, literalType, literalExpr,
|
|
|
|
isFileScope);
|
2007-07-19 09:06:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Action::ExprResult Sema::
|
2007-09-16 11:34:24 +08:00
|
|
|
ActOnInitList(SourceLocation LBraceLoc, ExprTy **initlist, unsigned NumInit,
|
2008-10-27 07:35:51 +08:00
|
|
|
InitListDesignations &Designators,
|
2007-08-31 12:56:16 +08:00
|
|
|
SourceLocation RBraceLoc) {
|
2007-09-02 10:04:30 +08:00
|
|
|
Expr **InitList = reinterpret_cast<Expr**>(initlist);
|
2007-08-31 12:56:16 +08:00
|
|
|
|
2007-09-16 02:49:24 +08:00
|
|
|
// Semantic analysis for initializers is done by ActOnDeclarator() and
|
2007-09-03 09:24:23 +08:00
|
|
|
// CheckInitializer() - it requires knowledge of the object being intialized.
|
2007-08-31 12:56:16 +08:00
|
|
|
|
2008-10-27 07:43:26 +08:00
|
|
|
InitListExpr *E = new InitListExpr(LBraceLoc, InitList, NumInit, RBraceLoc,
|
|
|
|
Designators.hasAnyDesignators());
|
2008-04-02 12:24:33 +08:00
|
|
|
E->setType(Context.VoidTy); // FIXME: just a place holder for now.
|
|
|
|
return E;
|
2007-07-19 09:06:55 +08:00
|
|
|
}
|
|
|
|
|
2008-08-17 04:27:34 +08:00
|
|
|
/// CheckCastTypes - Check type constraints for casting between types.
|
2008-08-20 11:55:42 +08:00
|
|
|
bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr) {
|
2008-08-17 04:27:34 +08:00
|
|
|
UsualUnaryConversions(castExpr);
|
|
|
|
|
|
|
|
// C99 6.5.4p2: the cast type needs to be void or scalar and the expression
|
|
|
|
// type needs to be scalar.
|
|
|
|
if (castType->isVoidType()) {
|
|
|
|
// Cast to void allows any expr type.
|
2008-12-06 07:32:09 +08:00
|
|
|
} else if (castType->isDependentType() || castExpr->isTypeDependent()) {
|
|
|
|
// We can't check any more until template instantiation time.
|
2008-08-17 04:27:34 +08:00
|
|
|
} else if (!castType->isScalarType() && !castType->isVectorType()) {
|
|
|
|
// GCC struct/union extension: allow cast to self.
|
|
|
|
if (Context.getCanonicalType(castType) !=
|
|
|
|
Context.getCanonicalType(castExpr->getType()) ||
|
|
|
|
(!castType->isStructureType() && !castType->isUnionType())) {
|
|
|
|
// Reject any other conversions to non-scalar types.
|
2008-11-19 13:08:23 +08:00
|
|
|
return Diag(TyR.getBegin(), diag::err_typecheck_cond_expect_scalar)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< castType << castExpr->getSourceRange();
|
2008-08-17 04:27:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// accept this, but emit an ext-warn.
|
2008-11-19 13:08:23 +08:00
|
|
|
Diag(TyR.getBegin(), diag::ext_typecheck_cast_nonscalar)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< castType << castExpr->getSourceRange();
|
2008-08-17 04:27:34 +08:00
|
|
|
} else if (!castExpr->getType()->isScalarType() &&
|
|
|
|
!castExpr->getType()->isVectorType()) {
|
2008-11-19 13:08:23 +08:00
|
|
|
return Diag(castExpr->getLocStart(),
|
|
|
|
diag::err_typecheck_expect_scalar_operand)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< castExpr->getType() << castExpr->getSourceRange();
|
2008-08-17 04:27:34 +08:00
|
|
|
} else if (castExpr->getType()->isVectorType()) {
|
|
|
|
if (CheckVectorCast(TyR, castExpr->getType(), castType))
|
|
|
|
return true;
|
|
|
|
} else if (castType->isVectorType()) {
|
|
|
|
if (CheckVectorCast(TyR, castType, castExpr->getType()))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2007-12-20 08:44:32 +08:00
|
|
|
bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty) {
|
2007-11-27 13:51:55 +08:00
|
|
|
assert(VectorTy->isVectorType() && "Not a vector type!");
|
|
|
|
|
|
|
|
if (Ty->isVectorType() || Ty->isIntegerType()) {
|
2008-03-06 02:54:05 +08:00
|
|
|
if (Context.getTypeSize(VectorTy) != Context.getTypeSize(Ty))
|
2007-11-27 13:51:55 +08:00
|
|
|
return Diag(R.getBegin(),
|
|
|
|
Ty->isVectorType() ?
|
|
|
|
diag::err_invalid_conversion_between_vectors :
|
2008-11-19 13:08:23 +08:00
|
|
|
diag::err_invalid_conversion_between_vector_and_integer)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< VectorTy << Ty << R;
|
2007-11-27 13:51:55 +08:00
|
|
|
} else
|
|
|
|
return Diag(R.getBegin(),
|
2008-11-19 13:08:23 +08:00
|
|
|
diag::err_invalid_conversion_between_vector_and_scalar)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< VectorTy << Ty << R;
|
2007-11-27 13:51:55 +08:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2006-11-10 13:29:30 +08:00
|
|
|
Action::ExprResult Sema::
|
2007-09-16 11:34:24 +08:00
|
|
|
ActOnCastExpr(SourceLocation LParenLoc, TypeTy *Ty,
|
2006-11-10 13:29:30 +08:00
|
|
|
SourceLocation RParenLoc, ExprTy *Op) {
|
2007-09-16 11:34:24 +08:00
|
|
|
assert((Ty != 0) && (Op != 0) && "ActOnCastExpr(): missing type or expr");
|
2007-07-17 07:25:18 +08:00
|
|
|
|
|
|
|
Expr *castExpr = static_cast<Expr*>(Op);
|
|
|
|
QualType castType = QualType::getFromOpaquePtr(Ty);
|
|
|
|
|
2008-08-17 04:27:34 +08:00
|
|
|
if (CheckCastTypes(SourceRange(LParenLoc, RParenLoc), castType, castExpr))
|
|
|
|
return true;
|
2008-11-04 07:29:32 +08:00
|
|
|
return new CStyleCastExpr(castType, castExpr, castType, LParenLoc, RParenLoc);
|
2006-11-10 13:29:30 +08:00
|
|
|
}
|
|
|
|
|
2007-11-26 09:40:58 +08:00
|
|
|
/// Note that lex is not null here, even if this is the gnu "x ?: y" extension.
|
|
|
|
/// In that case, lex = cond.
|
2007-05-16 04:29:32 +08:00
|
|
|
inline QualType Sema::CheckConditionalOperands( // C99 6.5.15
|
2007-07-14 00:58:59 +08:00
|
|
|
Expr *&cond, Expr *&lex, Expr *&rex, SourceLocation questionLoc) {
|
2007-07-17 05:54:35 +08:00
|
|
|
UsualUnaryConversions(cond);
|
|
|
|
UsualUnaryConversions(lex);
|
|
|
|
UsualUnaryConversions(rex);
|
|
|
|
QualType condT = cond->getType();
|
|
|
|
QualType lexT = lex->getType();
|
|
|
|
QualType rexT = rex->getType();
|
|
|
|
|
2007-05-17 03:47:19 +08:00
|
|
|
// first, check the condition.
|
2008-12-06 07:32:09 +08:00
|
|
|
if (!cond->isTypeDependent()) {
|
|
|
|
if (!condT->isScalarType()) { // C99 6.5.15p2
|
|
|
|
Diag(cond->getLocStart(), diag::err_typecheck_cond_expect_scalar) << condT;
|
|
|
|
return QualType();
|
|
|
|
}
|
2007-05-17 03:47:19 +08:00
|
|
|
}
|
2008-01-07 06:42:25 +08:00
|
|
|
|
|
|
|
// Now check the two expressions.
|
2008-12-06 07:32:09 +08:00
|
|
|
if ((lex && lex->isTypeDependent()) || (rex && rex->isTypeDependent()))
|
|
|
|
return Context.DependentTy;
|
|
|
|
|
2008-01-07 06:42:25 +08:00
|
|
|
// If both operands have arithmetic type, do the usual arithmetic conversions
|
|
|
|
// to find a common type: C99 6.5.15p3,5.
|
|
|
|
if (lexT->isArithmeticType() && rexT->isArithmeticType()) {
|
2007-07-17 08:58:39 +08:00
|
|
|
UsualArithmeticConversions(lex, rex);
|
|
|
|
return lex->getType();
|
|
|
|
}
|
2008-01-07 06:42:25 +08:00
|
|
|
|
|
|
|
// If both operands are the same structure or union type, the result is that
|
|
|
|
// type.
|
2007-08-01 05:27:01 +08:00
|
|
|
if (const RecordType *LHSRT = lexT->getAsRecordType()) { // C99 6.5.15p3
|
2008-01-07 06:42:25 +08:00
|
|
|
if (const RecordType *RHSRT = rexT->getAsRecordType())
|
2007-11-26 09:40:58 +08:00
|
|
|
if (LHSRT->getDecl() == RHSRT->getDecl())
|
2008-01-07 06:42:25 +08:00
|
|
|
// "If both the operands have structure or union type, the result has
|
|
|
|
// that type." This implies that CV qualifiers are dropped.
|
|
|
|
return lexT.getUnqualifiedType();
|
2007-05-17 03:47:19 +08:00
|
|
|
}
|
2008-01-07 06:42:25 +08:00
|
|
|
|
|
|
|
// C99 6.5.15p5: "If both operands have void type, the result has void type."
|
2008-05-13 05:44:38 +08:00
|
|
|
// The following || allows only one side to be void (a GCC-ism).
|
|
|
|
if (lexT->isVoidType() || rexT->isVoidType()) {
|
2008-06-05 03:47:51 +08:00
|
|
|
if (!lexT->isVoidType())
|
2008-11-19 13:27:50 +08:00
|
|
|
Diag(rex->getLocStart(), diag::ext_typecheck_cond_one_void)
|
|
|
|
<< rex->getSourceRange();
|
2008-05-13 05:44:38 +08:00
|
|
|
if (!rexT->isVoidType())
|
2008-11-19 13:27:50 +08:00
|
|
|
Diag(lex->getLocStart(), diag::ext_typecheck_cond_one_void)
|
|
|
|
<< lex->getSourceRange();
|
2008-06-05 03:47:51 +08:00
|
|
|
ImpCastExprToType(lex, Context.VoidTy);
|
|
|
|
ImpCastExprToType(rex, Context.VoidTy);
|
|
|
|
return Context.VoidTy;
|
2008-05-13 05:44:38 +08:00
|
|
|
}
|
2008-01-08 09:11:38 +08:00
|
|
|
// C99 6.5.15p6 - "if one operand is a null pointer constant, the result has
|
|
|
|
// the type of the other operand."
|
2008-09-12 07:12:46 +08:00
|
|
|
if ((lexT->isPointerType() || lexT->isBlockPointerType() ||
|
|
|
|
Context.isObjCObjectPointerType(lexT)) &&
|
2008-12-01 14:28:23 +08:00
|
|
|
rex->isNullPointerConstant(Context)) {
|
2008-01-17 03:17:22 +08:00
|
|
|
ImpCastExprToType(rex, lexT); // promote the null to a pointer.
|
2008-01-08 09:11:38 +08:00
|
|
|
return lexT;
|
|
|
|
}
|
2008-09-12 07:12:46 +08:00
|
|
|
if ((rexT->isPointerType() || rexT->isBlockPointerType() ||
|
|
|
|
Context.isObjCObjectPointerType(rexT)) &&
|
2008-12-01 14:28:23 +08:00
|
|
|
lex->isNullPointerConstant(Context)) {
|
2008-01-17 03:17:22 +08:00
|
|
|
ImpCastExprToType(lex, rexT); // promote the null to a pointer.
|
2008-01-08 09:11:38 +08:00
|
|
|
return rexT;
|
|
|
|
}
|
2008-01-07 06:50:31 +08:00
|
|
|
// Handle the case where both operands are pointers before we handle null
|
|
|
|
// pointer constants in case both operands are null pointer constants.
|
2007-08-01 05:27:01 +08: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() &&
|
2008-04-02 14:59:01 +08:00
|
|
|
rhptee->isIncompleteOrObjectType()) {
|
2008-02-21 04:55:12 +08:00
|
|
|
// Figure out necessary qualifiers (C99 6.5.15p6)
|
|
|
|
QualType destPointee=lhptee.getQualifiedType(rhptee.getCVRQualifiers());
|
2008-02-11 06:59:36 +08:00
|
|
|
QualType destType = Context.getPointerType(destPointee);
|
|
|
|
ImpCastExprToType(lex, destType); // add qualifiers if necessary
|
|
|
|
ImpCastExprToType(rex, destType); // promote to void*
|
|
|
|
return destType;
|
|
|
|
}
|
2008-04-02 14:59:01 +08:00
|
|
|
if (rhptee->isVoidType() && lhptee->isIncompleteOrObjectType()) {
|
2008-02-21 04:55:12 +08:00
|
|
|
QualType destPointee=rhptee.getQualifiedType(lhptee.getCVRQualifiers());
|
2008-02-11 06:59:36 +08:00
|
|
|
QualType destType = Context.getPointerType(destPointee);
|
|
|
|
ImpCastExprToType(lex, destType); // add qualifiers if necessary
|
|
|
|
ImpCastExprToType(rex, destType); // promote to void*
|
|
|
|
return destType;
|
|
|
|
}
|
2007-08-01 05:27:01 +08:00
|
|
|
|
2008-09-12 07:12:46 +08:00
|
|
|
QualType compositeType = lexT;
|
|
|
|
|
|
|
|
// If either type is an Objective-C object type then check
|
|
|
|
// compatibility according to Objective-C.
|
|
|
|
if (Context.isObjCObjectPointerType(lexT) ||
|
|
|
|
Context.isObjCObjectPointerType(rexT)) {
|
|
|
|
// If both operands are interfaces and either operand can be
|
|
|
|
// assigned to the other, use that type as the composite
|
|
|
|
// type. This allows
|
|
|
|
// xxx ? (A*) a : (B*) b
|
|
|
|
// where B is a subclass of A.
|
|
|
|
//
|
|
|
|
// Additionally, as for assignment, if either type is 'id'
|
|
|
|
// allow silent coercion. Finally, if the types are
|
|
|
|
// incompatible then make sure to use 'id' as the composite
|
|
|
|
// type so the result is acceptable for sending messages to.
|
|
|
|
|
|
|
|
// FIXME: This code should not be localized to here. Also this
|
|
|
|
// should use a compatible check instead of abusing the
|
|
|
|
// canAssignObjCInterfaces code.
|
|
|
|
const ObjCInterfaceType* LHSIface = lhptee->getAsObjCInterfaceType();
|
|
|
|
const ObjCInterfaceType* RHSIface = rhptee->getAsObjCInterfaceType();
|
|
|
|
if (LHSIface && RHSIface &&
|
|
|
|
Context.canAssignObjCInterfaces(LHSIface, RHSIface)) {
|
|
|
|
compositeType = lexT;
|
|
|
|
} else if (LHSIface && RHSIface &&
|
2008-11-26 14:43:45 +08:00
|
|
|
Context.canAssignObjCInterfaces(RHSIface, LHSIface)) {
|
2008-09-12 07:12:46 +08:00
|
|
|
compositeType = rexT;
|
|
|
|
} else if (Context.isObjCIdType(lhptee) ||
|
|
|
|
Context.isObjCIdType(rhptee)) {
|
|
|
|
// FIXME: This code looks wrong, because isObjCIdType checks
|
|
|
|
// the struct but getObjCIdType returns the pointer to
|
|
|
|
// struct. This is horrible and should be fixed.
|
|
|
|
compositeType = Context.getObjCIdType();
|
|
|
|
} else {
|
|
|
|
QualType incompatTy = Context.getObjCIdType();
|
|
|
|
ImpCastExprToType(lex, incompatTy);
|
|
|
|
ImpCastExprToType(rex, incompatTy);
|
|
|
|
return incompatTy;
|
|
|
|
}
|
|
|
|
} else if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(),
|
|
|
|
rhptee.getUnqualifiedType())) {
|
2008-11-19 06:52:51 +08:00
|
|
|
Diag(questionLoc, diag::warn_typecheck_cond_incompatible_pointers)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< lexT << rexT << lex->getSourceRange() << rex->getSourceRange();
|
2008-09-12 07:12:46 +08:00
|
|
|
// In this situation, we assume void* type. No especially good
|
|
|
|
// reason, but this is what gcc does, and we do have to pick
|
|
|
|
// to get a consistent AST.
|
|
|
|
QualType incompatTy = Context.getPointerType(Context.VoidTy);
|
2008-08-26 08:41:39 +08:00
|
|
|
ImpCastExprToType(lex, incompatTy);
|
|
|
|
ImpCastExprToType(rex, incompatTy);
|
|
|
|
return incompatTy;
|
2007-08-01 05:27:01 +08:00
|
|
|
}
|
|
|
|
// The pointer types are compatible.
|
2007-08-31 01:45:32 +08: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.
|
2008-05-17 04:37:07 +08:00
|
|
|
// FIXME: Need to calculate the composite type.
|
2008-02-11 06:59:36 +08:00
|
|
|
// FIXME: Need to add qualifiers
|
2008-05-17 04:37:07 +08:00
|
|
|
ImpCastExprToType(lex, compositeType);
|
|
|
|
ImpCastExprToType(rex, compositeType);
|
|
|
|
return compositeType;
|
2007-05-17 03:47:19 +08:00
|
|
|
}
|
|
|
|
}
|
2008-09-12 07:12:46 +08:00
|
|
|
// Need to handle "id<xx>" explicitly. Unlike "id", whose canonical type
|
|
|
|
// evaluates to "struct objc_object *" (and is handled above when comparing
|
|
|
|
// id with statically typed objects).
|
|
|
|
if (lexT->isObjCQualifiedIdType() || rexT->isObjCQualifiedIdType()) {
|
|
|
|
// GCC allows qualified id and any Objective-C type to devolve to
|
|
|
|
// id. Currently localizing to here until clear this should be
|
|
|
|
// part of ObjCQualifiedIdTypesAreCompatible.
|
|
|
|
if (ObjCQualifiedIdTypesAreCompatible(lexT, rexT, true) ||
|
|
|
|
(lexT->isObjCQualifiedIdType() &&
|
|
|
|
Context.isObjCObjectPointerType(rexT)) ||
|
|
|
|
(rexT->isObjCQualifiedIdType() &&
|
|
|
|
Context.isObjCObjectPointerType(lexT))) {
|
|
|
|
// FIXME: This is not the correct composite type. This only
|
|
|
|
// happens to work because id can more or less be used anywhere,
|
|
|
|
// however this may change the type of method sends.
|
|
|
|
// FIXME: gcc adds some type-checking of the arguments and emits
|
|
|
|
// (confusing) incompatible comparison warnings in some
|
|
|
|
// cases. Investigate.
|
|
|
|
QualType compositeType = Context.getObjCIdType();
|
|
|
|
ImpCastExprToType(lex, compositeType);
|
|
|
|
ImpCastExprToType(rex, compositeType);
|
|
|
|
return compositeType;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-09-11 03:17:48 +08:00
|
|
|
// Selection between block pointer types is ok as long as they are the same.
|
|
|
|
if (lexT->isBlockPointerType() && rexT->isBlockPointerType() &&
|
|
|
|
Context.getCanonicalType(lexT) == Context.getCanonicalType(rexT))
|
|
|
|
return lexT;
|
|
|
|
|
2008-01-07 06:42:25 +08:00
|
|
|
// Otherwise, the operands are not compatible.
|
2008-11-19 06:52:51 +08:00
|
|
|
Diag(questionLoc, diag::err_typecheck_cond_incompatible_operands)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< lexT << rexT << lex->getSourceRange() << rex->getSourceRange();
|
2007-05-17 03:47:19 +08:00
|
|
|
return QualType();
|
2007-05-16 04:29:32 +08:00
|
|
|
}
|
|
|
|
|
2007-09-16 11:34:24 +08:00
|
|
|
/// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null
|
2006-11-10 13:29:30 +08:00
|
|
|
/// in the case of a the GNU conditional expr extension.
|
2007-09-16 11:34:24 +08:00
|
|
|
Action::ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
|
2006-11-10 13:29:30 +08:00
|
|
|
SourceLocation ColonLoc,
|
|
|
|
ExprTy *Cond, ExprTy *LHS,
|
|
|
|
ExprTy *RHS) {
|
2007-07-17 05:39:03 +08:00
|
|
|
Expr *CondExpr = (Expr *) Cond;
|
|
|
|
Expr *LHSExpr = (Expr *) LHS, *RHSExpr = (Expr *) RHS;
|
2007-11-26 09:40:58 +08:00
|
|
|
|
|
|
|
// If this is the gnu "x ?: y" extension, analyze the types as though the LHS
|
|
|
|
// was the condition.
|
|
|
|
bool isLHSNull = LHSExpr == 0;
|
|
|
|
if (isLHSNull)
|
|
|
|
LHSExpr = CondExpr;
|
|
|
|
|
2007-07-17 05:39:03 +08:00
|
|
|
QualType result = CheckConditionalOperands(CondExpr, LHSExpr,
|
|
|
|
RHSExpr, QuestionLoc);
|
2007-05-16 04:29:32 +08:00
|
|
|
if (result.isNull())
|
|
|
|
return true;
|
2007-11-26 09:40:58 +08:00
|
|
|
return new ConditionalOperator(CondExpr, isLHSNull ? 0 : LHSExpr,
|
|
|
|
RHSExpr, result);
|
2006-11-10 13:29:30 +08:00
|
|
|
}
|
|
|
|
|
2007-03-24 06:27:02 +08:00
|
|
|
|
2007-05-12 06:18:03 +08: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.
|
2008-01-05 02:04:52 +08:00
|
|
|
Sema::AssignConvertType
|
2007-06-07 02:38:38 +08:00
|
|
|
Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) {
|
2007-05-12 06:18:03 +08:00
|
|
|
QualType lhptee, rhptee;
|
2007-05-11 12:00:31 +08:00
|
|
|
|
|
|
|
// get the "pointed to" type (ignoring qualifiers at the top level)
|
2007-08-01 05:27:01 +08:00
|
|
|
lhptee = lhsType->getAsPointerType()->getPointeeType();
|
|
|
|
rhptee = rhsType->getAsPointerType()->getPointeeType();
|
2007-05-11 12:00:31 +08:00
|
|
|
|
|
|
|
// make sure we operate on the canonical type
|
2008-07-27 06:17:49 +08:00
|
|
|
lhptee = Context.getCanonicalType(lhptee);
|
|
|
|
rhptee = Context.getCanonicalType(rhptee);
|
2007-05-12 06:18:03 +08:00
|
|
|
|
2008-01-05 02:04:52 +08:00
|
|
|
AssignConvertType ConvTy = Compatible;
|
2007-06-07 02:38:38 +08:00
|
|
|
|
2007-05-12 06:18:03 +08: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;
|
2008-02-21 04:55:12 +08:00
|
|
|
// FIXME: Handle ASQualType
|
2008-10-22 07:43:52 +08:00
|
|
|
if (!lhptee.isAtLeastAsQualifiedAs(rhptee))
|
2008-01-05 02:04:52 +08:00
|
|
|
ConvTy = CompatiblePointerDiscardsQualifiers;
|
2007-05-12 06:18:03 +08:00
|
|
|
|
|
|
|
// 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...
|
2008-01-04 06:56:36 +08:00
|
|
|
if (lhptee->isVoidType()) {
|
2008-04-02 14:59:01 +08:00
|
|
|
if (rhptee->isIncompleteOrObjectType())
|
2008-01-05 02:04:52 +08:00
|
|
|
return ConvTy;
|
2008-01-04 06:56:36 +08:00
|
|
|
|
|
|
|
// As an extension, we allow cast to/from void* to function pointer.
|
2008-04-02 14:59:01 +08:00
|
|
|
assert(rhptee->isFunctionType());
|
|
|
|
return FunctionVoidPointer;
|
2008-01-04 06:56:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (rhptee->isVoidType()) {
|
2008-04-02 14:59:01 +08:00
|
|
|
if (lhptee->isIncompleteOrObjectType())
|
2008-01-05 02:04:52 +08:00
|
|
|
return ConvTy;
|
2008-01-04 06:56:36 +08:00
|
|
|
|
|
|
|
// As an extension, we allow cast to/from void* to function pointer.
|
2008-04-02 14:59:01 +08:00
|
|
|
assert(lhptee->isFunctionType());
|
|
|
|
return FunctionVoidPointer;
|
2008-01-04 06:56:36 +08:00
|
|
|
}
|
2008-08-22 08:56:42 +08:00
|
|
|
|
|
|
|
// Check for ObjC interfaces
|
|
|
|
const ObjCInterfaceType* LHSIface = lhptee->getAsObjCInterfaceType();
|
|
|
|
const ObjCInterfaceType* RHSIface = rhptee->getAsObjCInterfaceType();
|
|
|
|
if (LHSIface && RHSIface &&
|
|
|
|
Context.canAssignObjCInterfaces(LHSIface, RHSIface))
|
|
|
|
return ConvTy;
|
|
|
|
|
|
|
|
// ID acts sort of like void* for ObjC interfaces
|
|
|
|
if (LHSIface && Context.isObjCIdType(rhptee))
|
|
|
|
return ConvTy;
|
|
|
|
if (RHSIface && Context.isObjCIdType(lhptee))
|
|
|
|
return ConvTy;
|
|
|
|
|
2007-05-12 06:18:03 +08:00
|
|
|
// C99 6.5.16.1p1 (constraint 3): both operands are pointers to qualified or
|
|
|
|
// unqualified versions of compatible types, ...
|
2008-01-04 06:56:36 +08:00
|
|
|
if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(),
|
|
|
|
rhptee.getUnqualifiedType()))
|
|
|
|
return IncompatiblePointer; // this "trumps" PointerAssignDiscardsQualifiers
|
2008-01-05 02:04:52 +08:00
|
|
|
return ConvTy;
|
2007-05-11 12:00:31 +08:00
|
|
|
}
|
|
|
|
|
2008-09-04 23:10:53 +08:00
|
|
|
/// CheckBlockPointerTypesForAssignment - This routine determines whether two
|
|
|
|
/// block pointer types are compatible or whether a block and normal pointer
|
|
|
|
/// are compatible. It is more restrict than comparing two function pointer
|
|
|
|
// types.
|
|
|
|
Sema::AssignConvertType
|
|
|
|
Sema::CheckBlockPointerTypesForAssignment(QualType lhsType,
|
|
|
|
QualType rhsType) {
|
|
|
|
QualType lhptee, rhptee;
|
|
|
|
|
|
|
|
// get the "pointed to" type (ignoring qualifiers at the top level)
|
|
|
|
lhptee = lhsType->getAsBlockPointerType()->getPointeeType();
|
|
|
|
rhptee = rhsType->getAsBlockPointerType()->getPointeeType();
|
|
|
|
|
|
|
|
// make sure we operate on the canonical type
|
|
|
|
lhptee = Context.getCanonicalType(lhptee);
|
|
|
|
rhptee = Context.getCanonicalType(rhptee);
|
|
|
|
|
|
|
|
AssignConvertType ConvTy = Compatible;
|
|
|
|
|
|
|
|
// For blocks we enforce that qualifiers are identical.
|
|
|
|
if (lhptee.getCVRQualifiers() != rhptee.getCVRQualifiers())
|
|
|
|
ConvTy = CompatiblePointerDiscardsQualifiers;
|
|
|
|
|
|
|
|
if (!Context.typesAreBlockCompatible(lhptee, rhptee))
|
|
|
|
return IncompatibleBlockPointer;
|
|
|
|
return ConvTy;
|
|
|
|
}
|
|
|
|
|
2007-06-07 02:38:38 +08:00
|
|
|
/// CheckAssignmentConstraints (C99 6.5.16) - This routine currently
|
2007-05-04 05:03:48 +08: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.
|
|
|
|
///
|
2008-01-05 02:04:52 +08:00
|
|
|
Sema::AssignConvertType
|
2007-06-07 02:38:38 +08:00
|
|
|
Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
|
2008-01-05 07:18:45 +08:00
|
|
|
// Get canonical types. We're not formatting these types, just comparing
|
|
|
|
// them.
|
2008-07-27 06:17:49 +08:00
|
|
|
lhsType = Context.getCanonicalType(lhsType).getUnqualifiedType();
|
|
|
|
rhsType = Context.getCanonicalType(rhsType).getUnqualifiedType();
|
2008-05-31 02:07:22 +08:00
|
|
|
|
|
|
|
if (lhsType == rhsType)
|
2008-01-08 01:51:46 +08:00
|
|
|
return Compatible; // Common case: fast path an exact match.
|
2007-07-25 05:46:40 +08:00
|
|
|
|
2008-10-28 08:22:11 +08:00
|
|
|
// If the left-hand side is a reference type, then we are in a
|
|
|
|
// (rare!) case where we've allowed the use of references in C,
|
|
|
|
// e.g., as a parameter type in a built-in function. In this case,
|
|
|
|
// just make sure that the type referenced is compatible with the
|
|
|
|
// right-hand side type. The caller is responsible for adjusting
|
|
|
|
// lhsType so that the resulting expression does not have reference
|
|
|
|
// type.
|
|
|
|
if (const ReferenceType *lhsTypeRef = lhsType->getAsReferenceType()) {
|
|
|
|
if (Context.typesAreCompatible(lhsTypeRef->getPointeeType(), rhsType))
|
2007-10-13 07:56:29 +08:00
|
|
|
return Compatible;
|
2008-01-05 07:18:45 +08:00
|
|
|
return Incompatible;
|
2007-12-20 01:45:58 +08:00
|
|
|
}
|
2008-05-31 02:07:22 +08:00
|
|
|
|
2008-04-07 13:30:13 +08:00
|
|
|
if (lhsType->isObjCQualifiedIdType() || rhsType->isObjCQualifiedIdType()) {
|
|
|
|
if (ObjCQualifiedIdTypesAreCompatible(lhsType, rhsType, false))
|
2007-12-20 01:45:58 +08:00
|
|
|
return Compatible;
|
2008-06-03 22:04:54 +08:00
|
|
|
// Relax integer conversions like we do for pointers below.
|
|
|
|
if (rhsType->isIntegerType())
|
|
|
|
return IntToPointer;
|
|
|
|
if (lhsType->isIntegerType())
|
|
|
|
return PointerToInt;
|
2008-10-15 06:18:38 +08:00
|
|
|
return IncompatibleObjCQualifiedId;
|
2007-12-20 01:45:58 +08:00
|
|
|
}
|
2008-01-05 07:32:24 +08:00
|
|
|
|
2008-07-15 02:02:46 +08:00
|
|
|
if (lhsType->isVectorType() || rhsType->isVectorType()) {
|
2008-04-19 07:10:10 +08:00
|
|
|
// For ExtVector, allow vector splats; float -> <n x float>
|
2008-07-15 02:02:46 +08:00
|
|
|
if (const ExtVectorType *LV = lhsType->getAsExtVectorType())
|
|
|
|
if (LV->getElementType() == rhsType)
|
2008-01-05 07:32:24 +08:00
|
|
|
return Compatible;
|
2008-05-31 02:07:22 +08:00
|
|
|
|
2008-07-15 02:02:46 +08:00
|
|
|
// If we are allowing lax vector conversions, and LHS and RHS are both
|
|
|
|
// vectors, the total size only needs to be the same. This is a bitcast;
|
|
|
|
// no bits are changed but the result type is different.
|
2008-01-05 07:32:24 +08:00
|
|
|
if (getLangOptions().LaxVectorConversions &&
|
|
|
|
lhsType->isVectorType() && rhsType->isVectorType()) {
|
2008-07-15 02:02:46 +08:00
|
|
|
if (Context.getTypeSize(lhsType) == Context.getTypeSize(rhsType))
|
|
|
|
return Compatible;
|
2008-01-05 07:32:24 +08:00
|
|
|
}
|
|
|
|
return Incompatible;
|
|
|
|
}
|
2008-05-31 02:07:22 +08:00
|
|
|
|
2008-01-05 07:32:24 +08:00
|
|
|
if (lhsType->isArithmeticType() && rhsType->isArithmeticType())
|
2007-06-07 02:38:38 +08:00
|
|
|
return Compatible;
|
2008-05-31 02:07:22 +08:00
|
|
|
|
2008-04-07 14:49:41 +08:00
|
|
|
if (isa<PointerType>(lhsType)) {
|
2007-06-07 02:38:38 +08:00
|
|
|
if (rhsType->isIntegerType())
|
2008-01-05 02:22:42 +08:00
|
|
|
return IntToPointer;
|
2008-05-31 02:07:22 +08:00
|
|
|
|
2008-04-07 14:49:41 +08:00
|
|
|
if (isa<PointerType>(rhsType))
|
2007-06-07 02:38:38 +08:00
|
|
|
return CheckPointerTypesForAssignment(lhsType, rhsType);
|
2008-09-04 23:10:53 +08:00
|
|
|
|
2008-09-30 02:10:17 +08:00
|
|
|
if (rhsType->getAsBlockPointerType()) {
|
2008-09-06 06:11:13 +08:00
|
|
|
if (lhsType->getAsPointerType()->getPointeeType()->isVoidType())
|
2008-11-27 08:44:28 +08:00
|
|
|
return Compatible;
|
2008-09-30 02:10:17 +08:00
|
|
|
|
|
|
|
// Treat block pointers as objects.
|
|
|
|
if (getLangOptions().ObjC1 &&
|
|
|
|
lhsType == Context.getCanonicalType(Context.getObjCIdType()))
|
|
|
|
return Compatible;
|
|
|
|
}
|
2008-09-04 23:10:53 +08:00
|
|
|
return Incompatible;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isa<BlockPointerType>(lhsType)) {
|
|
|
|
if (rhsType->isIntegerType())
|
|
|
|
return IntToPointer;
|
|
|
|
|
2008-09-30 02:10:17 +08:00
|
|
|
// Treat block pointers as objects.
|
|
|
|
if (getLangOptions().ObjC1 &&
|
|
|
|
rhsType == Context.getCanonicalType(Context.getObjCIdType()))
|
|
|
|
return Compatible;
|
|
|
|
|
2008-09-04 23:10:53 +08:00
|
|
|
if (rhsType->isBlockPointerType())
|
|
|
|
return CheckBlockPointerTypesForAssignment(lhsType, rhsType);
|
|
|
|
|
|
|
|
if (const PointerType *RHSPT = rhsType->getAsPointerType()) {
|
|
|
|
if (RHSPT->getPointeeType()->isVoidType())
|
2008-11-27 08:44:28 +08:00
|
|
|
return Compatible;
|
2008-09-04 23:10:53 +08:00
|
|
|
}
|
2008-01-05 07:18:45 +08:00
|
|
|
return Incompatible;
|
|
|
|
}
|
|
|
|
|
2008-04-07 14:49:41 +08:00
|
|
|
if (isa<PointerType>(rhsType)) {
|
2007-06-07 02:38:38 +08:00
|
|
|
// C99 6.5.16.1p1: the left operand is _Bool and the right is a pointer.
|
2008-05-31 02:07:22 +08:00
|
|
|
if (lhsType == Context.BoolTy)
|
|
|
|
return Compatible;
|
|
|
|
|
|
|
|
if (lhsType->isIntegerType())
|
2008-01-05 02:22:42 +08:00
|
|
|
return PointerToInt;
|
2007-06-07 02:38:38 +08:00
|
|
|
|
2008-04-07 14:49:41 +08:00
|
|
|
if (isa<PointerType>(lhsType))
|
2007-06-07 02:38:38 +08:00
|
|
|
return CheckPointerTypesForAssignment(lhsType, rhsType);
|
2008-09-04 23:10:53 +08:00
|
|
|
|
|
|
|
if (isa<BlockPointerType>(lhsType) &&
|
|
|
|
rhsType->getAsPointerType()->getPointeeType()->isVoidType())
|
2008-11-27 08:44:28 +08:00
|
|
|
return Compatible;
|
2008-01-05 07:18:45 +08:00
|
|
|
return Incompatible;
|
|
|
|
}
|
2008-05-31 02:07:22 +08:00
|
|
|
|
2008-01-05 07:18:45 +08:00
|
|
|
if (isa<TagType>(lhsType) && isa<TagType>(rhsType)) {
|
2008-04-07 14:49:41 +08:00
|
|
|
if (Context.typesAreCompatible(lhsType, rhsType))
|
2007-06-07 02:38:38 +08:00
|
|
|
return Compatible;
|
2007-05-30 14:30:29 +08:00
|
|
|
}
|
2007-06-07 02:38:38 +08:00
|
|
|
return Incompatible;
|
2007-05-03 05:58:15 +08:00
|
|
|
}
|
|
|
|
|
2008-01-05 02:04:52 +08:00
|
|
|
Sema::AssignConvertType
|
2007-07-14 07:32:42 +08:00
|
|
|
Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {
|
2008-10-22 07:43:52 +08:00
|
|
|
if (getLangOptions().CPlusPlus) {
|
|
|
|
if (!lhsType->isRecordType()) {
|
|
|
|
// C++ 5.17p3: If the left operand is not of class type, the
|
|
|
|
// expression is implicitly converted (C++ 4) to the
|
|
|
|
// cv-unqualified type of the left operand.
|
2008-10-24 12:54:22 +08:00
|
|
|
if (PerformImplicitConversion(rExpr, lhsType.getUnqualifiedType()))
|
2008-10-22 07:43:52 +08:00
|
|
|
return Incompatible;
|
2008-10-24 12:54:22 +08:00
|
|
|
else
|
2008-10-22 07:43:52 +08:00
|
|
|
return Compatible;
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: Currently, we fall through and treat C++ classes like C
|
|
|
|
// structures.
|
|
|
|
}
|
|
|
|
|
2007-11-28 01:58:44 +08:00
|
|
|
// C99 6.5.16.1p1: the left operand is a pointer and the right is
|
|
|
|
// a null pointer constant.
|
2008-09-05 00:56:14 +08:00
|
|
|
if ((lhsType->isPointerType() || lhsType->isObjCQualifiedIdType() ||
|
|
|
|
lhsType->isBlockPointerType())
|
2008-01-04 02:46:52 +08:00
|
|
|
&& rExpr->isNullPointerConstant(Context)) {
|
2008-01-17 03:17:22 +08:00
|
|
|
ImpCastExprToType(rExpr, lhsType);
|
2007-11-28 01:58:44 +08:00
|
|
|
return Compatible;
|
|
|
|
}
|
2008-09-04 23:10:53 +08:00
|
|
|
|
|
|
|
// We don't allow conversion of non-null-pointer constants to integers.
|
|
|
|
if (lhsType->isBlockPointerType() && rExpr->getType()->isIntegerType())
|
|
|
|
return IntToBlockPointer;
|
|
|
|
|
2007-10-16 10:55:40 +08:00
|
|
|
// This check seems unnatural, however it is necessary to ensure the proper
|
2007-07-14 07:32:42 +08:00
|
|
|
// conversion of functions/arrays. If the conversion were done for all
|
2007-09-16 02:49:24 +08:00
|
|
|
// DeclExpr's (created by ActOnIdentifierExpr), it would mess up the unary
|
2007-07-14 07:32:42 +08:00
|
|
|
// expressions that surpress this implicit conversion (&, sizeof).
|
2007-10-16 10:55:40 +08:00
|
|
|
//
|
2008-10-28 08:22:11 +08:00
|
|
|
// Suppress this for references: C++ 8.5.3p5.
|
2007-10-16 10:55:40 +08:00
|
|
|
if (!lhsType->isReferenceType())
|
|
|
|
DefaultFunctionArrayConversion(rExpr);
|
2007-08-25 06:33:52 +08:00
|
|
|
|
2008-01-05 02:04:52 +08:00
|
|
|
Sema::AssignConvertType result =
|
|
|
|
CheckAssignmentConstraints(lhsType, rExpr->getType());
|
2007-07-14 07:32:42 +08:00
|
|
|
|
2007-08-25 06:33:52 +08:00
|
|
|
// C99 6.5.16.1p2: The value of the right operand is converted to the
|
|
|
|
// type of the assignment expression.
|
2008-10-28 08:22:11 +08:00
|
|
|
// CheckAssignmentConstraints allows the left-hand side to be a reference,
|
|
|
|
// so that we can use references in built-in functions even in C.
|
|
|
|
// The getNonReferenceType() call makes sure that the resulting expression
|
|
|
|
// does not have reference type.
|
2007-08-25 06:33:52 +08:00
|
|
|
if (rExpr->getType() != lhsType)
|
2008-10-28 08:22:11 +08:00
|
|
|
ImpCastExprToType(rExpr, lhsType.getNonReferenceType());
|
2007-08-25 06:33:52 +08:00
|
|
|
return result;
|
2007-07-14 07:32:42 +08:00
|
|
|
}
|
|
|
|
|
2008-01-05 02:04:52 +08:00
|
|
|
Sema::AssignConvertType
|
2007-07-14 07:32:42 +08:00
|
|
|
Sema::CheckCompoundAssignmentConstraints(QualType lhsType, QualType rhsType) {
|
|
|
|
return CheckAssignmentConstraints(lhsType, rhsType);
|
|
|
|
}
|
|
|
|
|
2008-11-18 09:30:42 +08:00
|
|
|
QualType Sema::InvalidOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) {
|
2008-11-19 06:52:51 +08:00
|
|
|
Diag(Loc, diag::err_typecheck_invalid_operands)
|
2008-11-23 17:13:29 +08:00
|
|
|
<< lex->getType() << rex->getType()
|
2008-11-19 06:52:51 +08:00
|
|
|
<< lex->getSourceRange() << rex->getSourceRange();
|
2007-12-12 13:47:28 +08:00
|
|
|
return QualType();
|
2007-05-29 22:23:36 +08:00
|
|
|
}
|
|
|
|
|
2008-11-18 09:30:42 +08:00
|
|
|
inline QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex,
|
2007-07-14 00:58:59 +08:00
|
|
|
Expr *&rex) {
|
2008-04-04 09:30:25 +08:00
|
|
|
// For conversion purposes, we ignore any qualifiers.
|
|
|
|
// For example, "const float" and "float" are equivalent.
|
2008-07-27 06:17:49 +08:00
|
|
|
QualType lhsType =
|
|
|
|
Context.getCanonicalType(lex->getType()).getUnqualifiedType();
|
|
|
|
QualType rhsType =
|
|
|
|
Context.getCanonicalType(rex->getType()).getUnqualifiedType();
|
2007-07-10 05:31:10 +08:00
|
|
|
|
2008-07-15 02:02:46 +08:00
|
|
|
// If the vector types are identical, return.
|
2008-04-04 09:30:25 +08:00
|
|
|
if (lhsType == rhsType)
|
2007-07-10 05:31:10 +08:00
|
|
|
return lhsType;
|
2007-12-30 10:59:45 +08:00
|
|
|
|
2008-07-15 02:02:46 +08:00
|
|
|
// Handle the case of a vector & extvector type of the same size and element
|
|
|
|
// type. It would be nice if we only had one vector type someday.
|
|
|
|
if (getLangOptions().LaxVectorConversions)
|
|
|
|
if (const VectorType *LV = lhsType->getAsVectorType())
|
|
|
|
if (const VectorType *RV = rhsType->getAsVectorType())
|
|
|
|
if (LV->getElementType() == RV->getElementType() &&
|
|
|
|
LV->getNumElements() == RV->getNumElements())
|
|
|
|
return lhsType->isExtVectorType() ? lhsType : rhsType;
|
|
|
|
|
|
|
|
// If the lhs is an extended vector and the rhs is a scalar of the same type
|
|
|
|
// or a literal, promote the rhs to the vector type.
|
2008-04-19 07:10:10 +08:00
|
|
|
if (const ExtVectorType *V = lhsType->getAsExtVectorType()) {
|
2008-07-15 02:02:46 +08:00
|
|
|
QualType eltType = V->getElementType();
|
|
|
|
|
|
|
|
if ((eltType->getAsBuiltinType() == rhsType->getAsBuiltinType()) ||
|
|
|
|
(eltType->isIntegerType() && isa<IntegerLiteral>(rex)) ||
|
|
|
|
(eltType->isFloatingType() && isa<FloatingLiteral>(rex))) {
|
2008-01-17 03:17:22 +08:00
|
|
|
ImpCastExprToType(rex, lhsType);
|
2007-12-30 10:59:45 +08:00
|
|
|
return lhsType;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-07-15 02:02:46 +08:00
|
|
|
// If the rhs is an extended vector and the lhs is a scalar of the same type,
|
2007-12-30 10:59:45 +08:00
|
|
|
// promote the lhs to the vector type.
|
2008-04-19 07:10:10 +08:00
|
|
|
if (const ExtVectorType *V = rhsType->getAsExtVectorType()) {
|
2008-07-15 02:02:46 +08:00
|
|
|
QualType eltType = V->getElementType();
|
|
|
|
|
|
|
|
if ((eltType->getAsBuiltinType() == lhsType->getAsBuiltinType()) ||
|
|
|
|
(eltType->isIntegerType() && isa<IntegerLiteral>(lex)) ||
|
|
|
|
(eltType->isFloatingType() && isa<FloatingLiteral>(lex))) {
|
2008-01-17 03:17:22 +08:00
|
|
|
ImpCastExprToType(lex, rhsType);
|
2007-12-30 10:59:45 +08:00
|
|
|
return rhsType;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-10 05:31:10 +08:00
|
|
|
// You cannot convert between vector values of different size.
|
2008-11-19 06:52:51 +08:00
|
|
|
Diag(Loc, diag::err_typecheck_vector_not_convertable)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< lex->getType() << rex->getType()
|
2008-11-19 06:52:51 +08:00
|
|
|
<< lex->getSourceRange() << rex->getSourceRange();
|
2007-07-10 05:31:10 +08:00
|
|
|
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-05 05:54:46 +08:00
|
|
|
inline QualType Sema::CheckMultiplyDivideOperands(
|
2008-11-18 09:30:42 +08:00
|
|
|
Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign)
|
2007-04-21 07:42:24 +08:00
|
|
|
{
|
2007-07-14 07:32:42 +08:00
|
|
|
QualType lhsType = lex->getType(), rhsType = rex->getType();
|
|
|
|
|
|
|
|
if (lhsType->isVectorType() || rhsType->isVectorType())
|
2008-11-18 09:30:42 +08:00
|
|
|
return CheckVectorOperands(Loc, lex, rex);
|
2007-07-14 00:58:59 +08:00
|
|
|
|
2007-08-25 03:07:16 +08:00
|
|
|
QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
|
2007-04-21 07:42:24 +08:00
|
|
|
|
2007-07-17 08:58:39 +08:00
|
|
|
if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
|
2007-08-25 03:07:16 +08:00
|
|
|
return compType;
|
2008-11-18 09:30:42 +08:00
|
|
|
return InvalidOperands(Loc, lex, rex);
|
2007-03-31 07:47:58 +08: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-05 05:54:46 +08:00
|
|
|
inline QualType Sema::CheckRemainderOperands(
|
2008-11-18 09:30:42 +08: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-05 05:54:46 +08:00
|
|
|
{
|
2007-07-14 07:32:42 +08:00
|
|
|
QualType lhsType = lex->getType(), rhsType = rex->getType();
|
|
|
|
|
2007-08-25 03:07:16 +08: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-05 05:54:46 +08:00
|
|
|
|
2007-07-17 08:58:39 +08:00
|
|
|
if (lex->getType()->isIntegerType() && rex->getType()->isIntegerType())
|
2007-08-25 03:07:16 +08:00
|
|
|
return compType;
|
2008-11-18 09:30:42 +08:00
|
|
|
return 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-05 05:54:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
inline QualType Sema::CheckAdditionOperands( // C99 6.5.6
|
2008-11-18 09:30:42 +08:00
|
|
|
Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign)
|
2007-04-24 08:23:05 +08:00
|
|
|
{
|
2007-07-17 06:23:01 +08:00
|
|
|
if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
|
2008-11-18 09:30:42 +08:00
|
|
|
return CheckVectorOperands(Loc, lex, rex);
|
2007-07-14 00:58:59 +08:00
|
|
|
|
2007-08-25 03:07:16 +08:00
|
|
|
QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
|
2008-05-19 02:08:51 +08:00
|
|
|
|
2007-04-28 02:30:00 +08:00
|
|
|
// handle the common case first (both operands are arithmetic).
|
2007-07-17 08:58:39 +08:00
|
|
|
if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
|
2007-08-25 03:07:16 +08: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-05 05:54:46 +08:00
|
|
|
|
2008-05-19 02:08:51 +08:00
|
|
|
// Put any potential pointer into PExp
|
|
|
|
Expr* PExp = lex, *IExp = rex;
|
|
|
|
if (IExp->getType()->isPointerType())
|
|
|
|
std::swap(PExp, IExp);
|
|
|
|
|
|
|
|
if (const PointerType* PTy = PExp->getType()->getAsPointerType()) {
|
|
|
|
if (IExp->getType()->isIntegerType()) {
|
|
|
|
// Check for arithmetic on pointers to incomplete types
|
|
|
|
if (!PTy->getPointeeType()->isObjectType()) {
|
|
|
|
if (PTy->getPointeeType()->isVoidType()) {
|
2008-11-19 13:08:23 +08:00
|
|
|
Diag(Loc, diag::ext_gnu_void_ptr)
|
|
|
|
<< lex->getSourceRange() << rex->getSourceRange();
|
2008-05-19 02:08:51 +08:00
|
|
|
} else {
|
2008-11-19 13:08:23 +08:00
|
|
|
Diag(Loc, diag::err_typecheck_arithmetic_incomplete_type)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< lex->getType() << lex->getSourceRange();
|
2008-05-19 02:08:51 +08:00
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return PExp->getType();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-18 09:30:42 +08:00
|
|
|
return InvalidOperands(Loc, lex, rex);
|
2007-03-22 05:08:52 +08:00
|
|
|
}
|
|
|
|
|
2008-04-07 13:30:13 +08:00
|
|
|
// C99 6.5.6
|
|
|
|
QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex,
|
2008-11-18 09:30:42 +08:00
|
|
|
SourceLocation Loc, bool isCompAssign) {
|
2007-07-17 06:23:01 +08:00
|
|
|
if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
|
2008-11-18 09:30:42 +08:00
|
|
|
return CheckVectorOperands(Loc, lex, rex);
|
2007-07-14 07:32:42 +08:00
|
|
|
|
2007-08-25 03:07:16 +08:00
|
|
|
QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
|
2007-04-24 08:23:05 +08:00
|
|
|
|
2007-12-10 05:53:25 +08:00
|
|
|
// Enforce type constraints: C99 6.5.6p3.
|
|
|
|
|
|
|
|
// Handle the common case first (both operands are arithmetic).
|
2007-07-17 08:58:39 +08:00
|
|
|
if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
|
2007-08-25 03:07:16 +08:00
|
|
|
return compType;
|
2007-12-10 05:53:25 +08:00
|
|
|
|
|
|
|
// Either ptr - int or ptr - ptr.
|
|
|
|
if (const PointerType *LHSPTy = lex->getType()->getAsPointerType()) {
|
2008-01-30 02:58:14 +08:00
|
|
|
QualType lpointee = LHSPTy->getPointeeType();
|
2008-02-08 09:19:44 +08:00
|
|
|
|
2007-12-10 05:53:25 +08:00
|
|
|
// The LHS must be an object type, not incomplete, function, etc.
|
2008-01-30 02:58:14 +08:00
|
|
|
if (!lpointee->isObjectType()) {
|
2007-12-10 05:53:25 +08:00
|
|
|
// Handle the GNU void* extension.
|
2008-01-30 02:58:14 +08:00
|
|
|
if (lpointee->isVoidType()) {
|
2008-11-19 13:08:23 +08:00
|
|
|
Diag(Loc, diag::ext_gnu_void_ptr)
|
|
|
|
<< lex->getSourceRange() << rex->getSourceRange();
|
2007-12-10 05:53:25 +08:00
|
|
|
} else {
|
2008-11-19 13:08:23 +08:00
|
|
|
Diag(Loc, diag::err_typecheck_sub_ptr_object)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< lex->getType() << lex->getSourceRange();
|
2007-12-10 05:53:25 +08:00
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// The result type of a pointer-int computation is the pointer type.
|
|
|
|
if (rex->getType()->isIntegerType())
|
|
|
|
return lex->getType();
|
2007-07-17 06:23:01 +08:00
|
|
|
|
2007-12-10 05:53:25 +08:00
|
|
|
// Handle pointer-pointer subtractions.
|
|
|
|
if (const PointerType *RHSPTy = rex->getType()->getAsPointerType()) {
|
2008-02-08 09:19:44 +08:00
|
|
|
QualType rpointee = RHSPTy->getPointeeType();
|
|
|
|
|
2007-12-10 05:53:25 +08:00
|
|
|
// RHS must be an object type, unless void (GNU).
|
2008-01-30 02:58:14 +08:00
|
|
|
if (!rpointee->isObjectType()) {
|
2007-12-10 05:53:25 +08:00
|
|
|
// Handle the GNU void* extension.
|
2008-01-30 02:58:14 +08:00
|
|
|
if (rpointee->isVoidType()) {
|
|
|
|
if (!lpointee->isVoidType())
|
2008-11-19 13:08:23 +08:00
|
|
|
Diag(Loc, diag::ext_gnu_void_ptr)
|
|
|
|
<< lex->getSourceRange() << rex->getSourceRange();
|
2007-12-10 05:53:25 +08:00
|
|
|
} else {
|
2008-11-19 13:08:23 +08:00
|
|
|
Diag(Loc, diag::err_typecheck_sub_ptr_object)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< rex->getType() << rex->getSourceRange();
|
2007-12-10 05:53:25 +08:00
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Pointee types must be compatible.
|
2008-09-02 13:09:35 +08:00
|
|
|
if (!Context.typesAreCompatible(
|
|
|
|
Context.getCanonicalType(lpointee).getUnqualifiedType(),
|
|
|
|
Context.getCanonicalType(rpointee).getUnqualifiedType())) {
|
2008-11-19 06:52:51 +08:00
|
|
|
Diag(Loc, diag::err_typecheck_sub_ptr_compatible)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< lex->getType() << rex->getType()
|
2008-11-19 06:52:51 +08:00
|
|
|
<< lex->getSourceRange() << rex->getSourceRange();
|
2007-12-10 05:53:25 +08:00
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
|
|
|
return Context.getPointerDiffType();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-18 09:30:42 +08:00
|
|
|
return 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-05 05:54:46 +08:00
|
|
|
}
|
2007-04-24 08:23:05 +08:00
|
|
|
|
2008-04-07 13:30:13 +08:00
|
|
|
// C99 6.5.7
|
2008-11-18 09:30:42 +08:00
|
|
|
QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
|
2008-04-07 13:30:13 +08:00
|
|
|
bool isCompAssign) {
|
2007-12-12 13:47:28 +08:00
|
|
|
// C99 6.5.7p2: Each of the operands shall have integer type.
|
|
|
|
if (!lex->getType()->isIntegerType() || !rex->getType()->isIntegerType())
|
2008-11-18 09:30:42 +08:00
|
|
|
return 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-05 05:54:46 +08:00
|
|
|
|
2007-12-12 13:47:28 +08:00
|
|
|
// Shifts don't perform usual arithmetic conversions, they just do integer
|
|
|
|
// promotions on each operand. C99 6.5.7p3
|
2007-12-13 15:28:16 +08:00
|
|
|
if (!isCompAssign)
|
|
|
|
UsualUnaryConversions(lex);
|
2007-12-12 13:47:28 +08:00
|
|
|
UsualUnaryConversions(rex);
|
|
|
|
|
|
|
|
// "The type of the result is that of the promoted left operand."
|
|
|
|
return lex->getType();
|
2007-03-22 05:08:52 +08:00
|
|
|
}
|
|
|
|
|
2008-08-22 08:56:42 +08:00
|
|
|
static bool areComparableObjCInterfaces(QualType LHS, QualType RHS,
|
|
|
|
ASTContext& Context) {
|
|
|
|
const ObjCInterfaceType* LHSIface = LHS->getAsObjCInterfaceType();
|
|
|
|
const ObjCInterfaceType* RHSIface = RHS->getAsObjCInterfaceType();
|
|
|
|
// ID acts sort of like void* for ObjC interfaces
|
|
|
|
if (LHSIface && Context.isObjCIdType(RHS))
|
|
|
|
return true;
|
|
|
|
if (RHSIface && Context.isObjCIdType(LHS))
|
|
|
|
return true;
|
|
|
|
if (!LHSIface || !RHSIface)
|
|
|
|
return false;
|
|
|
|
return Context.canAssignObjCInterfaces(LHSIface, RHSIface) ||
|
|
|
|
Context.canAssignObjCInterfaces(RHSIface, LHSIface);
|
|
|
|
}
|
|
|
|
|
2008-04-07 13:30:13 +08:00
|
|
|
// C99 6.5.8
|
2008-11-18 09:30:42 +08:00
|
|
|
QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
|
2008-04-07 13:30:13 +08:00
|
|
|
bool isRelational) {
|
2008-07-15 02:02:46 +08:00
|
|
|
if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
|
2008-11-18 09:30:42 +08:00
|
|
|
return CheckVectorCompareOperands(lex, rex, Loc, isRelational);
|
2008-07-15 02:02:46 +08:00
|
|
|
|
2007-08-26 09:18:55 +08:00
|
|
|
// C99 6.5.8p3 / C99 6.5.9p4
|
2007-08-11 02:26:40 +08:00
|
|
|
if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
|
|
|
|
UsualArithmeticConversions(lex, rex);
|
|
|
|
else {
|
|
|
|
UsualUnaryConversions(lex);
|
|
|
|
UsualUnaryConversions(rex);
|
|
|
|
}
|
2007-07-17 05:54:35 +08:00
|
|
|
QualType lType = lex->getType();
|
|
|
|
QualType rType = rex->getType();
|
2007-04-24 08:23:05 +08:00
|
|
|
|
2007-10-30 01:13:39 +08:00
|
|
|
// For non-floating point types, check for self-comparisons of the form
|
|
|
|
// x == x, x != x, x < x, etc. These always evaluate to a constant, and
|
|
|
|
// often indicate logic errors in the program.
|
2007-10-30 00:58:49 +08:00
|
|
|
if (!lType->isFloatingType()) {
|
2008-01-18 00:57:34 +08:00
|
|
|
if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(lex->IgnoreParens()))
|
|
|
|
if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(rex->IgnoreParens()))
|
2007-10-30 00:58:49 +08:00
|
|
|
if (DRL->getDecl() == DRR->getDecl())
|
2008-11-18 09:30:42 +08:00
|
|
|
Diag(Loc, diag::warn_selfcomparison);
|
2007-10-30 00:58:49 +08:00
|
|
|
}
|
|
|
|
|
2008-11-19 11:25:36 +08:00
|
|
|
// The result of comparisons is 'bool' in C++, 'int' in C.
|
|
|
|
QualType ResultTy = getLangOptions().CPlusPlus? Context.BoolTy : Context.IntTy;
|
|
|
|
|
2007-08-26 09:18:55 +08:00
|
|
|
if (isRelational) {
|
|
|
|
if (lType->isRealType() && rType->isRealType())
|
2008-11-19 11:25:36 +08:00
|
|
|
return ResultTy;
|
2007-08-26 09:18:55 +08:00
|
|
|
} else {
|
2007-10-30 01:13:39 +08:00
|
|
|
// Check for comparisons of floating point operands using != and ==.
|
|
|
|
if (lType->isFloatingType()) {
|
|
|
|
assert (rType->isFloatingType());
|
2008-11-18 09:30:42 +08:00
|
|
|
CheckFloatComparison(Loc,lex,rex);
|
2007-10-30 00:40:01 +08:00
|
|
|
}
|
|
|
|
|
2007-08-26 09:18:55 +08:00
|
|
|
if (lType->isArithmeticType() && rType->isArithmeticType())
|
2008-11-19 11:25:36 +08:00
|
|
|
return ResultTy;
|
2007-08-26 09:18:55 +08:00
|
|
|
}
|
2007-04-28 02:30:00 +08:00
|
|
|
|
2007-08-26 09:10:14 +08:00
|
|
|
bool LHSIsNull = lex->isNullPointerConstant(Context);
|
|
|
|
bool RHSIsNull = rex->isNullPointerConstant(Context);
|
|
|
|
|
2007-08-26 09:18:55 +08: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 12:08:11 +08:00
|
|
|
if (lType->isPointerType() && rType->isPointerType()) { // C99 6.5.8p2
|
2008-04-03 13:07:25 +08:00
|
|
|
QualType LCanPointeeTy =
|
2008-07-27 06:17:49 +08:00
|
|
|
Context.getCanonicalType(lType->getAsPointerType()->getPointeeType());
|
2008-04-03 13:07:25 +08:00
|
|
|
QualType RCanPointeeTy =
|
2008-07-27 06:17:49 +08:00
|
|
|
Context.getCanonicalType(rType->getAsPointerType()->getPointeeType());
|
2008-02-08 09:19:44 +08:00
|
|
|
|
2007-11-13 22:57:38 +08:00
|
|
|
if (!LHSIsNull && !RHSIsNull && // C99 6.5.9p2
|
2008-04-03 13:07:25 +08:00
|
|
|
!LCanPointeeTy->isVoidType() && !RCanPointeeTy->isVoidType() &&
|
|
|
|
!Context.typesAreCompatible(LCanPointeeTy.getUnqualifiedType(),
|
2008-08-22 08:56:42 +08:00
|
|
|
RCanPointeeTy.getUnqualifiedType()) &&
|
|
|
|
!areComparableObjCInterfaces(LCanPointeeTy, RCanPointeeTy, Context)) {
|
2008-11-19 06:52:51 +08:00
|
|
|
Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< lType << rType << lex->getSourceRange() << rex->getSourceRange();
|
2007-06-14 05:41:08 +08:00
|
|
|
}
|
2008-01-17 03:17:22 +08:00
|
|
|
ImpCastExprToType(rex, lType); // promote the pointer to pointer
|
2008-11-19 11:25:36 +08:00
|
|
|
return ResultTy;
|
2007-08-17 05:48:38 +08:00
|
|
|
}
|
2008-09-04 23:10:53 +08:00
|
|
|
// Handle block pointer types.
|
|
|
|
if (lType->isBlockPointerType() && rType->isBlockPointerType()) {
|
|
|
|
QualType lpointee = lType->getAsBlockPointerType()->getPointeeType();
|
|
|
|
QualType rpointee = rType->getAsBlockPointerType()->getPointeeType();
|
|
|
|
|
|
|
|
if (!LHSIsNull && !RHSIsNull &&
|
|
|
|
!Context.typesAreBlockCompatible(lpointee, rpointee)) {
|
2008-11-19 06:52:51 +08:00
|
|
|
Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< lType << rType << lex->getSourceRange() << rex->getSourceRange();
|
2008-09-28 09:11:11 +08:00
|
|
|
}
|
|
|
|
ImpCastExprToType(rex, lType); // promote the pointer to pointer
|
2008-11-19 11:25:36 +08:00
|
|
|
return ResultTy;
|
2008-09-28 09:11:11 +08:00
|
|
|
}
|
|
|
|
// Allow block pointers to be compared with null pointer constants.
|
|
|
|
if ((lType->isBlockPointerType() && rType->isPointerType()) ||
|
|
|
|
(lType->isPointerType() && rType->isBlockPointerType())) {
|
|
|
|
if (!LHSIsNull && !RHSIsNull) {
|
2008-11-19 06:52:51 +08:00
|
|
|
Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< lType << rType << lex->getSourceRange() << rex->getSourceRange();
|
2008-09-04 23:10:53 +08:00
|
|
|
}
|
|
|
|
ImpCastExprToType(rex, lType); // promote the pointer to pointer
|
2008-11-19 11:25:36 +08:00
|
|
|
return ResultTy;
|
2008-09-04 23:10:53 +08:00
|
|
|
}
|
|
|
|
|
2008-06-03 22:04:54 +08:00
|
|
|
if ((lType->isObjCQualifiedIdType() || rType->isObjCQualifiedIdType())) {
|
2008-10-27 18:33:19 +08:00
|
|
|
if (lType->isPointerType() || rType->isPointerType()) {
|
2008-11-18 03:49:16 +08:00
|
|
|
const PointerType *LPT = lType->getAsPointerType();
|
|
|
|
const PointerType *RPT = rType->getAsPointerType();
|
|
|
|
bool LPtrToVoid = LPT ?
|
|
|
|
Context.getCanonicalType(LPT->getPointeeType())->isVoidType() : false;
|
|
|
|
bool RPtrToVoid = RPT ?
|
|
|
|
Context.getCanonicalType(RPT->getPointeeType())->isVoidType() : false;
|
|
|
|
|
|
|
|
if (!LPtrToVoid && !RPtrToVoid &&
|
|
|
|
!Context.typesAreCompatible(lType, rType)) {
|
2008-11-19 06:52:51 +08:00
|
|
|
Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< lType << rType << lex->getSourceRange() << rex->getSourceRange();
|
2008-10-27 18:33:19 +08:00
|
|
|
ImpCastExprToType(rex, lType);
|
2008-11-19 11:25:36 +08:00
|
|
|
return ResultTy;
|
2008-10-27 18:33:19 +08:00
|
|
|
}
|
2008-10-24 07:30:52 +08:00
|
|
|
ImpCastExprToType(rex, lType);
|
2008-11-19 11:25:36 +08:00
|
|
|
return ResultTy;
|
2008-10-21 02:19:10 +08:00
|
|
|
}
|
2008-06-03 22:04:54 +08:00
|
|
|
if (ObjCQualifiedIdTypesAreCompatible(lType, rType, true)) {
|
|
|
|
ImpCastExprToType(rex, lType);
|
2008-11-19 11:25:36 +08:00
|
|
|
return ResultTy;
|
2008-10-15 06:18:38 +08:00
|
|
|
} else {
|
|
|
|
if ((lType->isObjCQualifiedIdType() && rType->isObjCQualifiedIdType())) {
|
2008-11-19 06:52:51 +08:00
|
|
|
Diag(Loc, diag::warn_incompatible_qualified_id_operands)
|
2008-11-24 13:29:24 +08:00
|
|
|
<< lType << rType << lex->getSourceRange() << rex->getSourceRange();
|
2008-10-24 07:30:52 +08:00
|
|
|
ImpCastExprToType(rex, lType);
|
2008-11-19 11:25:36 +08:00
|
|
|
return ResultTy;
|
2008-10-15 06:18:38 +08:00
|
|
|
}
|
2008-06-03 22:04:54 +08:00
|
|
|
}
|
2007-12-20 09:06:58 +08:00
|
|
|
}
|
2008-06-03 22:04:54 +08:00
|
|
|
if ((lType->isPointerType() || lType->isObjCQualifiedIdType()) &&
|
|
|
|
rType->isIntegerType()) {
|
2007-08-26 09:10:14 +08:00
|
|
|
if (!RHSIsNull)
|
2008-11-19 06:52:51 +08:00
|
|
|
Diag(Loc, diag::ext_typecheck_comparison_of_pointer_integer)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< lType << rType << lex->getSourceRange() << rex->getSourceRange();
|
2008-01-17 03:17:22 +08:00
|
|
|
ImpCastExprToType(rex, lType); // promote the integer to pointer
|
2008-11-19 11:25:36 +08:00
|
|
|
return ResultTy;
|
2007-08-17 05:48:38 +08:00
|
|
|
}
|
2008-06-03 22:04:54 +08:00
|
|
|
if (lType->isIntegerType() &&
|
|
|
|
(rType->isPointerType() || rType->isObjCQualifiedIdType())) {
|
2007-08-26 09:10:14 +08:00
|
|
|
if (!LHSIsNull)
|
2008-11-19 06:52:51 +08:00
|
|
|
Diag(Loc, diag::ext_typecheck_comparison_of_pointer_integer)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< lType << rType << lex->getSourceRange() << rex->getSourceRange();
|
2008-01-17 03:17:22 +08:00
|
|
|
ImpCastExprToType(lex, rType); // promote the integer to pointer
|
2008-11-19 11:25:36 +08:00
|
|
|
return ResultTy;
|
2007-05-15 10:32:35 +08:00
|
|
|
}
|
2008-09-05 00:56:14 +08:00
|
|
|
// Handle block pointers.
|
|
|
|
if (lType->isBlockPointerType() && rType->isIntegerType()) {
|
|
|
|
if (!RHSIsNull)
|
2008-11-19 06:52:51 +08:00
|
|
|
Diag(Loc, diag::ext_typecheck_comparison_of_pointer_integer)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< lType << rType << lex->getSourceRange() << rex->getSourceRange();
|
2008-09-05 00:56:14 +08:00
|
|
|
ImpCastExprToType(rex, lType); // promote the integer to pointer
|
2008-11-19 11:25:36 +08:00
|
|
|
return ResultTy;
|
2008-09-05 00:56:14 +08:00
|
|
|
}
|
|
|
|
if (lType->isIntegerType() && rType->isBlockPointerType()) {
|
|
|
|
if (!LHSIsNull)
|
2008-11-19 06:52:51 +08:00
|
|
|
Diag(Loc, diag::ext_typecheck_comparison_of_pointer_integer)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< lType << rType << lex->getSourceRange() << rex->getSourceRange();
|
2008-09-05 00:56:14 +08:00
|
|
|
ImpCastExprToType(lex, rType); // promote the integer to pointer
|
2008-11-19 11:25:36 +08:00
|
|
|
return ResultTy;
|
2008-09-05 00:56:14 +08:00
|
|
|
}
|
2008-11-18 09:30:42 +08:00
|
|
|
return InvalidOperands(Loc, lex, rex);
|
2007-03-22 05:08:52 +08:00
|
|
|
}
|
|
|
|
|
2008-07-15 02:02:46 +08:00
|
|
|
/// CheckVectorCompareOperands - vector comparisons are a clang extension that
|
|
|
|
/// operates on extended vector types. Instead of producing an IntTy result,
|
|
|
|
/// like a scalar comparison, a vector comparison produces a vector of integer
|
|
|
|
/// types.
|
|
|
|
QualType Sema::CheckVectorCompareOperands(Expr *&lex, Expr *&rex,
|
2008-11-18 09:30:42 +08:00
|
|
|
SourceLocation Loc,
|
2008-07-15 02:02:46 +08:00
|
|
|
bool isRelational) {
|
|
|
|
// Check to make sure we're operating on vectors of the same type and width,
|
|
|
|
// Allowing one side to be a scalar of element type.
|
2008-11-18 09:30:42 +08:00
|
|
|
QualType vType = CheckVectorOperands(Loc, lex, rex);
|
2008-07-15 02:02:46 +08:00
|
|
|
if (vType.isNull())
|
|
|
|
return vType;
|
|
|
|
|
|
|
|
QualType lType = lex->getType();
|
|
|
|
QualType rType = rex->getType();
|
|
|
|
|
|
|
|
// For non-floating point types, check for self-comparisons of the form
|
|
|
|
// x == x, x != x, x < x, etc. These always evaluate to a constant, and
|
|
|
|
// often indicate logic errors in the program.
|
|
|
|
if (!lType->isFloatingType()) {
|
|
|
|
if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(lex->IgnoreParens()))
|
|
|
|
if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(rex->IgnoreParens()))
|
|
|
|
if (DRL->getDecl() == DRR->getDecl())
|
2008-11-18 09:30:42 +08:00
|
|
|
Diag(Loc, diag::warn_selfcomparison);
|
2008-07-15 02:02:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check for comparisons of floating point operands using != and ==.
|
|
|
|
if (!isRelational && lType->isFloatingType()) {
|
|
|
|
assert (rType->isFloatingType());
|
2008-11-18 09:30:42 +08:00
|
|
|
CheckFloatComparison(Loc,lex,rex);
|
2008-07-15 02:02:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Return the type for the comparison, which is the same as vector type for
|
|
|
|
// integer vectors, or an integer type of identical size and number of
|
|
|
|
// elements for floating point vectors.
|
|
|
|
if (lType->isIntegerType())
|
|
|
|
return lType;
|
|
|
|
|
|
|
|
const VectorType *VTy = lType->getAsVectorType();
|
|
|
|
|
|
|
|
// FIXME: need to deal with non-32b int / non-64b long long
|
|
|
|
unsigned TypeSize = Context.getTypeSize(VTy->getElementType());
|
|
|
|
if (TypeSize == 32) {
|
|
|
|
return Context.getExtVectorType(Context.IntTy, VTy->getNumElements());
|
|
|
|
}
|
|
|
|
assert(TypeSize == 64 && "Unhandled vector element size in vector compare");
|
|
|
|
return Context.getExtVectorType(Context.LongLongTy, VTy->getNumElements());
|
|
|
|
}
|
|
|
|
|
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-05 05:54:46 +08:00
|
|
|
inline QualType Sema::CheckBitwiseOperands(
|
2008-11-18 09:30:42 +08:00
|
|
|
Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign)
|
2007-04-24 08:23:05 +08:00
|
|
|
{
|
2007-07-17 06:23:01 +08:00
|
|
|
if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
|
2008-11-18 09:30:42 +08:00
|
|
|
return CheckVectorOperands(Loc, lex, rex);
|
2007-07-14 07:32:42 +08:00
|
|
|
|
2007-08-25 03:07:16 +08:00
|
|
|
QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
|
2007-04-24 08:23:05 +08:00
|
|
|
|
2007-07-17 08:58:39 +08:00
|
|
|
if (lex->getType()->isIntegerType() && rex->getType()->isIntegerType())
|
2007-08-25 03:07:16 +08:00
|
|
|
return compType;
|
2008-11-18 09:30:42 +08:00
|
|
|
return InvalidOperands(Loc, lex, rex);
|
2007-03-22 05:08:52 +08: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-05 05:54:46 +08:00
|
|
|
inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]
|
2008-11-18 09:30:42 +08:00
|
|
|
Expr *&lex, Expr *&rex, SourceLocation Loc)
|
2007-04-24 08:23:05 +08:00
|
|
|
{
|
2007-07-17 05:54:35 +08:00
|
|
|
UsualUnaryConversions(lex);
|
|
|
|
UsualUnaryConversions(rex);
|
2007-04-28 02:30:00 +08:00
|
|
|
|
2008-05-14 04:16:47 +08: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-05 05:54:46 +08:00
|
|
|
return Context.IntTy;
|
2008-11-18 09:30:42 +08:00
|
|
|
return InvalidOperands(Loc, lex, rex);
|
2007-04-27 04:39:23 +08:00
|
|
|
}
|
|
|
|
|
2008-11-18 09:22:49 +08:00
|
|
|
/// CheckForModifiableLvalue - Verify that E is a modifiable lvalue. If not,
|
|
|
|
/// emit an error and return true. If so, return false.
|
|
|
|
static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
|
|
|
|
Expr::isModifiableLvalueResult IsLV = E->isModifiableLvalue(S.Context);
|
|
|
|
if (IsLV == Expr::MLV_Valid)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
unsigned Diag = 0;
|
|
|
|
bool NeedType = false;
|
|
|
|
switch (IsLV) { // C99 6.5.16p2
|
|
|
|
default: assert(0 && "Unknown result from isModifiableLvalue!");
|
|
|
|
case Expr::MLV_ConstQualified: Diag = diag::err_typecheck_assign_const; break;
|
2008-01-05 02:04:52 +08:00
|
|
|
case Expr::MLV_ArrayType:
|
2008-11-18 09:22:49 +08:00
|
|
|
Diag = diag::err_typecheck_array_not_modifiable_lvalue;
|
|
|
|
NeedType = true;
|
|
|
|
break;
|
2008-01-05 02:04:52 +08:00
|
|
|
case Expr::MLV_NotObjectType:
|
2008-11-18 09:22:49 +08:00
|
|
|
Diag = diag::err_typecheck_non_object_not_modifiable_lvalue;
|
|
|
|
NeedType = true;
|
|
|
|
break;
|
2008-11-18 03:51:54 +08:00
|
|
|
case Expr::MLV_LValueCast:
|
2008-11-18 09:22:49 +08:00
|
|
|
Diag = diag::err_typecheck_lvalue_casts_not_supported;
|
|
|
|
break;
|
2008-01-05 02:04:52 +08:00
|
|
|
case Expr::MLV_InvalidExpression:
|
2008-11-18 09:22:49 +08:00
|
|
|
Diag = diag::err_typecheck_expression_not_modifiable_lvalue;
|
|
|
|
break;
|
2008-01-05 02:04:52 +08:00
|
|
|
case Expr::MLV_IncompleteType:
|
|
|
|
case Expr::MLV_IncompleteVoidType:
|
2008-11-18 09:22:49 +08:00
|
|
|
Diag = diag::err_typecheck_incomplete_type_not_modifiable_lvalue;
|
|
|
|
NeedType = true;
|
|
|
|
break;
|
2008-01-05 02:04:52 +08:00
|
|
|
case Expr::MLV_DuplicateVectorComponents:
|
2008-11-18 09:22:49 +08:00
|
|
|
Diag = diag::err_typecheck_duplicate_vector_components_not_mlvalue;
|
|
|
|
break;
|
2008-09-26 22:41:28 +08:00
|
|
|
case Expr::MLV_NotBlockQualified:
|
2008-11-18 09:22:49 +08:00
|
|
|
Diag = diag::err_block_decl_ref_not_modifiable_lvalue;
|
|
|
|
break;
|
2008-11-23 02:39:36 +08:00
|
|
|
case Expr::MLV_ReadonlyProperty:
|
|
|
|
Diag = diag::error_readonly_property_assignment;
|
|
|
|
break;
|
2008-11-23 04:25:50 +08:00
|
|
|
case Expr::MLV_NoSetterProperty:
|
|
|
|
Diag = diag::error_nosetter_property_assignment;
|
|
|
|
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-05 05:54:46 +08:00
|
|
|
}
|
2008-01-05 02:04:52 +08:00
|
|
|
|
2008-11-18 09:22:49 +08:00
|
|
|
if (NeedType)
|
2008-11-24 14:25:27 +08:00
|
|
|
S.Diag(Loc, Diag) << E->getType() << E->getSourceRange();
|
2008-11-18 09:22:49 +08:00
|
|
|
else
|
2008-11-19 13:27:50 +08:00
|
|
|
S.Diag(Loc, Diag) << E->getSourceRange();
|
2008-11-18 09:22:49 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// C99 6.5.16.1
|
2008-11-18 09:30:42 +08:00
|
|
|
QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS,
|
|
|
|
SourceLocation Loc,
|
|
|
|
QualType CompoundType) {
|
|
|
|
// Verify that LHS is a modifiable lvalue, and emit error if not.
|
|
|
|
if (CheckForModifiableLvalue(LHS, Loc, *this))
|
2008-11-18 09:22:49 +08:00
|
|
|
return QualType();
|
2008-11-18 09:30:42 +08:00
|
|
|
|
|
|
|
QualType LHSType = LHS->getType();
|
|
|
|
QualType RHSType = CompoundType.isNull() ? RHS->getType() : CompoundType;
|
2008-11-18 09:22:49 +08:00
|
|
|
|
2008-01-05 02:04:52 +08:00
|
|
|
AssignConvertType ConvTy;
|
2008-11-18 09:30:42 +08:00
|
|
|
if (CompoundType.isNull()) {
|
2008-08-22 02:04:13 +08:00
|
|
|
// Simple assignment "x = y".
|
2008-11-18 09:30:42 +08:00
|
|
|
ConvTy = CheckSingleAssignmentConstraints(LHSType, RHS);
|
2008-08-22 02:04:13 +08:00
|
|
|
|
|
|
|
// If the RHS is a unary plus or minus, check to see if they = and + are
|
|
|
|
// right next to each other. If so, the user may have typo'd "x =+ 4"
|
|
|
|
// instead of "x += 4".
|
2008-11-18 09:30:42 +08:00
|
|
|
Expr *RHSCheck = RHS;
|
2008-08-22 02:04:13 +08:00
|
|
|
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(RHSCheck))
|
|
|
|
RHSCheck = ICE->getSubExpr();
|
|
|
|
if (UnaryOperator *UO = dyn_cast<UnaryOperator>(RHSCheck)) {
|
|
|
|
if ((UO->getOpcode() == UnaryOperator::Plus ||
|
|
|
|
UO->getOpcode() == UnaryOperator::Minus) &&
|
2008-11-18 09:30:42 +08:00
|
|
|
Loc.isFileID() && UO->getOperatorLoc().isFileID() &&
|
2008-08-22 02:04:13 +08:00
|
|
|
// Only if the two operators are exactly adjacent.
|
2008-11-18 09:30:42 +08:00
|
|
|
Loc.getFileLocWithOffset(1) == UO->getOperatorLoc())
|
2008-11-20 14:06:08 +08:00
|
|
|
Diag(Loc, diag::warn_not_compound_assign)
|
|
|
|
<< (UO->getOpcode() == UnaryOperator::Plus ? "+" : "-")
|
|
|
|
<< SourceRange(UO->getOperatorLoc(), UO->getOperatorLoc());
|
2008-08-22 02:04:13 +08:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Compound assignment "x += y"
|
2008-11-18 09:30:42 +08:00
|
|
|
ConvTy = CheckCompoundAssignmentConstraints(LHSType, RHSType);
|
2008-08-22 02:04:13 +08:00
|
|
|
}
|
2007-07-31 20:34:36 +08:00
|
|
|
|
2008-11-18 09:30:42 +08:00
|
|
|
if (DiagnoseAssignmentResult(ConvTy, Loc, LHSType, RHSType,
|
|
|
|
RHS, "assigning"))
|
2008-01-05 02:04:52 +08:00
|
|
|
return QualType();
|
|
|
|
|
2007-06-07 02:38:38 +08: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-31 01:45:32 +08:00
|
|
|
// C++ 5.17p1: the type of the assignment expression is that of its left
|
|
|
|
// oprdu.
|
2008-11-18 09:30:42 +08:00
|
|
|
return 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-05 05:54:46 +08:00
|
|
|
}
|
|
|
|
|
2008-11-18 09:30:42 +08:00
|
|
|
// C99 6.5.17
|
|
|
|
QualType Sema::CheckCommaOperands(Expr *LHS, Expr *&RHS, SourceLocation Loc) {
|
|
|
|
// FIXME: what is required for LHS?
|
2008-07-26 04:54:07 +08:00
|
|
|
|
|
|
|
// Comma performs lvalue conversion (C99 6.3.2.1), but not unary conversions.
|
2008-11-18 09:30:42 +08:00
|
|
|
DefaultFunctionArrayConversion(RHS);
|
|
|
|
return RHS->getType();
|
2007-03-22 05:08:52 +08:00
|
|
|
}
|
|
|
|
|
2007-07-14 00:58:59 +08:00
|
|
|
/// CheckIncrementDecrementOperand - unlike most "Check" methods, this routine
|
|
|
|
/// doesn't need to call UsualUnaryConversions or UsualArithmeticConversions.
|
2008-11-21 15:05:48 +08:00
|
|
|
QualType Sema::CheckIncrementDecrementOperand(Expr *Op, SourceLocation OpLoc) {
|
|
|
|
QualType ResType = Op->getType();
|
|
|
|
assert(!ResType.isNull() && "no type for increment/decrement expression");
|
2007-04-06 05:15:20 +08:00
|
|
|
|
2007-08-25 01:20:07 +08:00
|
|
|
// C99 6.5.2.4p1: We allow complex as a GCC extension.
|
2008-11-21 15:05:48 +08:00
|
|
|
if (ResType->isRealType()) {
|
|
|
|
// OK!
|
|
|
|
} else if (const PointerType *PT = ResType->getAsPointerType()) {
|
|
|
|
// C99 6.5.2.4p2, 6.5.6p2
|
|
|
|
if (PT->getPointeeType()->isObjectType()) {
|
|
|
|
// Pointer to object is ok!
|
|
|
|
} else if (PT->getPointeeType()->isVoidType()) {
|
|
|
|
// Pointer to void is extension.
|
|
|
|
Diag(OpLoc, diag::ext_gnu_void_ptr) << Op->getSourceRange();
|
|
|
|
} else {
|
2008-11-19 13:27:50 +08:00
|
|
|
Diag(OpLoc, diag::err_typecheck_arithmetic_incomplete_type)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< ResType << Op->getSourceRange();
|
2007-08-25 01:20:07 +08:00
|
|
|
return QualType();
|
|
|
|
}
|
2008-11-21 15:05:48 +08:00
|
|
|
} else if (ResType->isComplexType()) {
|
|
|
|
// C99 does not support ++/-- on complex types, we allow as an extension.
|
|
|
|
Diag(OpLoc, diag::ext_integer_increment_complex)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< ResType << Op->getSourceRange();
|
2008-11-21 15:05:48 +08:00
|
|
|
} else {
|
|
|
|
Diag(OpLoc, diag::err_typecheck_illegal_increment_decrement)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< ResType << Op->getSourceRange();
|
2008-11-21 15:05:48 +08:00
|
|
|
return QualType();
|
2007-04-04 07:13:13 +08:00
|
|
|
}
|
2007-08-24 05:37:33 +08:00
|
|
|
// At this point, we know we have a real, complex or pointer type.
|
|
|
|
// Now make sure the operand is a modifiable lvalue.
|
2008-11-21 15:05:48 +08:00
|
|
|
if (CheckForModifiableLvalue(Op, OpLoc, *this))
|
2007-05-07 08:24:15 +08:00
|
|
|
return QualType();
|
2008-11-21 15:05:48 +08:00
|
|
|
return ResType;
|
2007-03-22 05:08:52 +08:00
|
|
|
}
|
|
|
|
|
2008-02-01 15:15:58 +08:00
|
|
|
/// getPrimaryDecl - Helper function for CheckAddressOfOperand().
|
2007-04-20 07:00:49 +08:00
|
|
|
/// This routine allows us to typecheck complex/recursive expressions
|
2008-08-05 04:02:37 +08:00
|
|
|
/// where the declaration is needed for type checking. We only need to
|
|
|
|
/// handle cases when the expression references a function designator
|
|
|
|
/// or is an lvalue. Here are some examples:
|
|
|
|
/// - &(x) => x
|
|
|
|
/// - &*****f => f for f a function designator.
|
|
|
|
/// - &s.xx => s
|
|
|
|
/// - &s.zz[1].yy -> s, if zz is an array
|
|
|
|
/// - *(x + 1) -> x, if x is an array
|
|
|
|
/// - &"123"[2] -> 0
|
|
|
|
/// - & __real__ x -> x
|
2008-10-22 00:13:35 +08:00
|
|
|
static NamedDecl *getPrimaryDecl(Expr *E) {
|
2008-04-02 12:24:33 +08:00
|
|
|
switch (E->getStmtClass()) {
|
2007-04-20 07:00:49 +08:00
|
|
|
case Stmt::DeclRefExprClass:
|
2008-04-02 12:24:33 +08:00
|
|
|
return cast<DeclRefExpr>(E)->getDecl();
|
2007-04-20 07:00:49 +08:00
|
|
|
case Stmt::MemberExprClass:
|
2007-11-17 01:46:48 +08:00
|
|
|
// Fields cannot be declared with a 'register' storage class.
|
|
|
|
// &X->f is always ok, even if X is declared register.
|
2008-04-02 12:24:33 +08:00
|
|
|
if (cast<MemberExpr>(E)->isArrow())
|
2007-11-17 01:46:48 +08:00
|
|
|
return 0;
|
2008-04-02 12:24:33 +08:00
|
|
|
return getPrimaryDecl(cast<MemberExpr>(E)->getBase());
|
2008-02-01 15:15:58 +08:00
|
|
|
case Stmt::ArraySubscriptExprClass: {
|
2008-08-05 04:02:37 +08:00
|
|
|
// &X[4] and &4[X] refers to X if X is not a pointer.
|
2008-02-01 15:15:58 +08:00
|
|
|
|
2008-10-22 00:13:35 +08:00
|
|
|
NamedDecl *D = getPrimaryDecl(cast<ArraySubscriptExpr>(E)->getBase());
|
2008-10-22 05:22:32 +08:00
|
|
|
ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
|
2008-02-02 00:01:31 +08:00
|
|
|
if (!VD || VD->getType()->isPointerType())
|
2008-02-01 15:15:58 +08:00
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return VD;
|
|
|
|
}
|
2008-08-05 04:02:37 +08:00
|
|
|
case Stmt::UnaryOperatorClass: {
|
|
|
|
UnaryOperator *UO = cast<UnaryOperator>(E);
|
|
|
|
|
|
|
|
switch(UO->getOpcode()) {
|
|
|
|
case UnaryOperator::Deref: {
|
|
|
|
// *(X + 1) refers to X if X is not a pointer.
|
2008-10-22 00:13:35 +08:00
|
|
|
if (NamedDecl *D = getPrimaryDecl(UO->getSubExpr())) {
|
|
|
|
ValueDecl *VD = dyn_cast<ValueDecl>(D);
|
|
|
|
if (!VD || VD->getType()->isPointerType())
|
|
|
|
return 0;
|
|
|
|
return VD;
|
|
|
|
}
|
|
|
|
return 0;
|
2008-08-05 04:02:37 +08:00
|
|
|
}
|
|
|
|
case UnaryOperator::Real:
|
|
|
|
case UnaryOperator::Imag:
|
|
|
|
case UnaryOperator::Extension:
|
|
|
|
return getPrimaryDecl(UO->getSubExpr());
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case Stmt::BinaryOperatorClass: {
|
|
|
|
BinaryOperator *BO = cast<BinaryOperator>(E);
|
|
|
|
|
|
|
|
// Handle cases involving pointer arithmetic. The result of an
|
|
|
|
// Assign or AddAssign is not an lvalue so they can be ignored.
|
|
|
|
|
|
|
|
// (x + n) or (n + x) => x
|
|
|
|
if (BO->getOpcode() == BinaryOperator::Add) {
|
|
|
|
if (BO->getLHS()->getType()->isPointerType()) {
|
|
|
|
return getPrimaryDecl(BO->getLHS());
|
|
|
|
} else if (BO->getRHS()->getType()->isPointerType()) {
|
|
|
|
return getPrimaryDecl(BO->getRHS());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2007-04-20 07:00:49 +08:00
|
|
|
case Stmt::ParenExprClass:
|
2008-04-02 12:24:33 +08:00
|
|
|
return getPrimaryDecl(cast<ParenExpr>(E)->getSubExpr());
|
2007-11-17 01:46:48 +08:00
|
|
|
case Stmt::ImplicitCastExprClass:
|
|
|
|
// &X[4] when X is an array, has an implicit cast from array to pointer.
|
2008-04-02 12:24:33 +08:00
|
|
|
return getPrimaryDecl(cast<ImplicitCastExpr>(E)->getSubExpr());
|
2007-04-20 07:00:49 +08: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-17 03:47:19 +08:00
|
|
|
/// operator (C99 6.3.2.1p[2-4]), and its result is never an lvalue.
|
2008-11-11 04:40:00 +08:00
|
|
|
/// In C++, the operand might be an overloaded function name, in which case
|
|
|
|
/// we allow the '&' but retain the overloaded-function type.
|
2007-05-07 08:24:15 +08:00
|
|
|
QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) {
|
2008-12-18 06:52:20 +08:00
|
|
|
if (op->isTypeDependent())
|
|
|
|
return Context.DependentTy;
|
|
|
|
|
2008-01-14 01:10:08 +08:00
|
|
|
if (getLangOptions().C99) {
|
|
|
|
// Implement C99-only parts of addressof rules.
|
|
|
|
if (UnaryOperator* uOp = dyn_cast<UnaryOperator>(op)) {
|
|
|
|
if (uOp->getOpcode() == UnaryOperator::Deref)
|
|
|
|
// Per C99 6.5.3.2, the address of a deref always returns a valid result
|
|
|
|
// (assuming the deref expression is valid).
|
|
|
|
return uOp->getSubExpr()->getType();
|
|
|
|
}
|
|
|
|
// Technically, there should be a check for array subscript
|
|
|
|
// expressions here, but the result of one is always an lvalue anyway.
|
|
|
|
}
|
2008-10-22 00:13:35 +08:00
|
|
|
NamedDecl *dcl = getPrimaryDecl(op);
|
2008-07-27 05:30:36 +08:00
|
|
|
Expr::isLvalueResult lval = op->isLvalue(Context);
|
2008-12-17 06:59:47 +08:00
|
|
|
|
2007-05-28 07:58:33 +08:00
|
|
|
if (lval != Expr::LV_Valid) { // C99 6.5.3.2p1
|
2007-11-17 01:46:48 +08:00
|
|
|
if (!dcl || !isa<FunctionDecl>(dcl)) {// allow function designators
|
|
|
|
// FIXME: emit more specific diag...
|
2008-11-19 13:27:50 +08:00
|
|
|
Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof)
|
|
|
|
<< op->getSourceRange();
|
2007-05-07 08:24:15 +08:00
|
|
|
return QualType();
|
|
|
|
}
|
2008-03-01 07:30:25 +08:00
|
|
|
} else if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(op)) { // C99 6.5.3.2p1
|
|
|
|
if (MemExpr->getMemberDecl()->isBitField()) {
|
2008-11-20 14:06:08 +08:00
|
|
|
Diag(OpLoc, diag::err_typecheck_address_of)
|
|
|
|
<< "bit-field" << op->getSourceRange();
|
2008-03-01 07:30:25 +08:00
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
// Check for Apple extension for accessing vector components.
|
|
|
|
} else if (isa<ArraySubscriptExpr>(op) &&
|
|
|
|
cast<ArraySubscriptExpr>(op)->getBase()->getType()->isVectorType()) {
|
2008-11-20 14:06:08 +08:00
|
|
|
Diag(OpLoc, diag::err_typecheck_address_of)
|
|
|
|
<< "vector" << op->getSourceRange();
|
2008-03-01 07:30:25 +08:00
|
|
|
return QualType();
|
|
|
|
} else if (dcl) { // C99 6.5.3.2p1
|
2007-04-20 07:00:49 +08:00
|
|
|
// 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 08:24:15 +08:00
|
|
|
if (vd->getStorageClass() == VarDecl::Register) {
|
2008-11-20 14:06:08 +08:00
|
|
|
Diag(OpLoc, diag::err_typecheck_address_of)
|
|
|
|
<< "register variable" << op->getSourceRange();
|
2007-05-07 08:24:15 +08:00
|
|
|
return QualType();
|
|
|
|
}
|
2008-12-11 05:26:49 +08:00
|
|
|
} else if (isa<OverloadedFunctionDecl>(dcl)) {
|
2008-11-11 04:40:00 +08:00
|
|
|
return Context.OverloadTy;
|
2008-12-11 05:26:49 +08:00
|
|
|
} else if (isa<FieldDecl>(dcl)) {
|
|
|
|
// Okay: we can take the address of a field.
|
2008-12-17 06:58:26 +08:00
|
|
|
} else if (isa<FunctionDecl>(dcl)) {
|
|
|
|
// Okay: we can take the address of a function.
|
2008-12-11 05:26:49 +08:00
|
|
|
}
|
2008-12-17 06:58:26 +08:00
|
|
|
else
|
2007-04-26 03:01:39 +08:00
|
|
|
assert(0 && "Unknown/unexpected decl type");
|
2007-04-20 07:00:49 +08:00
|
|
|
}
|
2008-07-27 08:48:22 +08:00
|
|
|
|
2007-04-20 07:00:49 +08:00
|
|
|
// If the operand has type "type", the result has type "pointer to type".
|
2007-05-07 08:24:15 +08:00
|
|
|
return Context.getPointerType(op->getType());
|
2007-04-20 07:00:49 +08:00
|
|
|
}
|
|
|
|
|
2008-11-23 17:13:29 +08:00
|
|
|
QualType Sema::CheckIndirectionOperand(Expr *Op, SourceLocation OpLoc) {
|
|
|
|
UsualUnaryConversions(Op);
|
|
|
|
QualType Ty = Op->getType();
|
2007-04-20 07:00:49 +08:00
|
|
|
|
2008-11-23 17:13:29 +08:00
|
|
|
// Note that per both C89 and C99, this is always legal, even if ptype is an
|
|
|
|
// incomplete type or void. It would be possible to warn about dereferencing
|
|
|
|
// a void pointer, but it's completely well-defined, and such a warning is
|
|
|
|
// unlikely to catch any mistakes.
|
|
|
|
if (const PointerType *PT = Ty->getAsPointerType())
|
2008-01-14 01:10:08 +08:00
|
|
|
return PT->getPointeeType();
|
2008-11-23 17:13:29 +08:00
|
|
|
|
2008-11-20 14:06:08 +08:00
|
|
|
Diag(OpLoc, diag::err_typecheck_indirection_requires_pointer)
|
2008-11-23 17:13:29 +08:00
|
|
|
<< Ty << Op->getSourceRange();
|
2007-05-07 08:24:15 +08:00
|
|
|
return QualType();
|
2007-04-24 08:23:05 +08: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-05 05:54:46 +08: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 08:24:15 +08: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___real: Opc = UnaryOperator::Real; break;
|
|
|
|
case tok::kw___imag: Opc = UnaryOperator::Imag; break;
|
2007-06-09 06:16:53 +08:00
|
|
|
case tok::kw___extension__: Opc = UnaryOperator::Extension; break;
|
2007-05-07 08:24:15 +08:00
|
|
|
}
|
|
|
|
return Opc;
|
|
|
|
}
|
|
|
|
|
2008-11-07 07:29:22 +08:00
|
|
|
/// CreateBuiltinBinOp - Creates a new built-in binary operation with
|
|
|
|
/// operator @p Opc at location @c TokLoc. This routine only supports
|
|
|
|
/// built-in operations; ActOnBinOp handles overloaded operators.
|
|
|
|
Action::ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
|
|
|
|
unsigned Op,
|
|
|
|
Expr *lhs, Expr *rhs) {
|
2007-06-28 11:53:10 +08:00
|
|
|
QualType ResultTy; // Result type of the binary operator.
|
|
|
|
QualType CompTy; // Computation type for compound assignments (e.g. '+=')
|
2008-11-07 07:29:22 +08:00
|
|
|
BinaryOperator::Opcode Opc = (BinaryOperator::Opcode)Op;
|
|
|
|
|
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-05 05:54:46 +08:00
|
|
|
switch (Opc) {
|
|
|
|
default:
|
|
|
|
assert(0 && "Unknown binary expr!");
|
|
|
|
case BinaryOperator::Assign:
|
2008-11-07 07:29:22 +08:00
|
|
|
ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, 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-05 05:54:46 +08:00
|
|
|
break;
|
|
|
|
case BinaryOperator::Mul:
|
|
|
|
case BinaryOperator::Div:
|
2008-11-07 07:29:22 +08:00
|
|
|
ResultTy = CheckMultiplyDivideOperands(lhs, rhs, OpLoc);
|
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-05 05:54:46 +08:00
|
|
|
break;
|
|
|
|
case BinaryOperator::Rem:
|
2008-11-07 07:29:22 +08:00
|
|
|
ResultTy = CheckRemainderOperands(lhs, rhs, OpLoc);
|
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-05 05:54:46 +08:00
|
|
|
break;
|
|
|
|
case BinaryOperator::Add:
|
2008-11-07 07:29:22 +08:00
|
|
|
ResultTy = CheckAdditionOperands(lhs, rhs, OpLoc);
|
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-05 05:54:46 +08:00
|
|
|
break;
|
|
|
|
case BinaryOperator::Sub:
|
2008-11-07 07:29:22 +08:00
|
|
|
ResultTy = CheckSubtractionOperands(lhs, rhs, OpLoc);
|
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-05 05:54:46 +08:00
|
|
|
break;
|
|
|
|
case BinaryOperator::Shl:
|
|
|
|
case BinaryOperator::Shr:
|
2008-11-07 07:29:22 +08:00
|
|
|
ResultTy = CheckShiftOperands(lhs, rhs, OpLoc);
|
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-05 05:54:46 +08:00
|
|
|
break;
|
|
|
|
case BinaryOperator::LE:
|
|
|
|
case BinaryOperator::LT:
|
|
|
|
case BinaryOperator::GE:
|
|
|
|
case BinaryOperator::GT:
|
2008-11-07 07:29:22 +08:00
|
|
|
ResultTy = CheckCompareOperands(lhs, rhs, OpLoc, 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-05 05:54:46 +08:00
|
|
|
break;
|
|
|
|
case BinaryOperator::EQ:
|
|
|
|
case BinaryOperator::NE:
|
2008-11-07 07:29:22 +08:00
|
|
|
ResultTy = CheckCompareOperands(lhs, rhs, OpLoc, 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-05 05:54:46 +08:00
|
|
|
break;
|
|
|
|
case BinaryOperator::And:
|
|
|
|
case BinaryOperator::Xor:
|
|
|
|
case BinaryOperator::Or:
|
2008-11-07 07:29:22 +08:00
|
|
|
ResultTy = CheckBitwiseOperands(lhs, rhs, OpLoc);
|
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-05 05:54:46 +08:00
|
|
|
break;
|
|
|
|
case BinaryOperator::LAnd:
|
|
|
|
case BinaryOperator::LOr:
|
2008-11-07 07:29:22 +08:00
|
|
|
ResultTy = CheckLogicalOperands(lhs, rhs, OpLoc);
|
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-05 05:54:46 +08:00
|
|
|
break;
|
|
|
|
case BinaryOperator::MulAssign:
|
|
|
|
case BinaryOperator::DivAssign:
|
2008-11-07 07:29:22 +08:00
|
|
|
CompTy = CheckMultiplyDivideOperands(lhs, rhs, OpLoc, true);
|
2007-06-28 11:53:10 +08:00
|
|
|
if (!CompTy.isNull())
|
2008-11-07 07:29:22 +08:00
|
|
|
ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, 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-05 05:54:46 +08:00
|
|
|
break;
|
|
|
|
case BinaryOperator::RemAssign:
|
2008-11-07 07:29:22 +08:00
|
|
|
CompTy = CheckRemainderOperands(lhs, rhs, OpLoc, true);
|
2007-06-28 11:53:10 +08:00
|
|
|
if (!CompTy.isNull())
|
2008-11-07 07:29:22 +08:00
|
|
|
ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, 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-05 05:54:46 +08:00
|
|
|
break;
|
|
|
|
case BinaryOperator::AddAssign:
|
2008-11-07 07:29:22 +08:00
|
|
|
CompTy = CheckAdditionOperands(lhs, rhs, OpLoc, true);
|
2007-06-28 11:53:10 +08:00
|
|
|
if (!CompTy.isNull())
|
2008-11-07 07:29:22 +08:00
|
|
|
ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, 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-05 05:54:46 +08:00
|
|
|
break;
|
|
|
|
case BinaryOperator::SubAssign:
|
2008-11-07 07:29:22 +08:00
|
|
|
CompTy = CheckSubtractionOperands(lhs, rhs, OpLoc, true);
|
2007-06-28 11:53:10 +08:00
|
|
|
if (!CompTy.isNull())
|
2008-11-07 07:29:22 +08:00
|
|
|
ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, 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-05 05:54:46 +08:00
|
|
|
break;
|
|
|
|
case BinaryOperator::ShlAssign:
|
|
|
|
case BinaryOperator::ShrAssign:
|
2008-11-07 07:29:22 +08:00
|
|
|
CompTy = CheckShiftOperands(lhs, rhs, OpLoc, true);
|
2007-06-28 11:53:10 +08:00
|
|
|
if (!CompTy.isNull())
|
2008-11-07 07:29:22 +08:00
|
|
|
ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, 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-05 05:54:46 +08:00
|
|
|
break;
|
|
|
|
case BinaryOperator::AndAssign:
|
|
|
|
case BinaryOperator::XorAssign:
|
|
|
|
case BinaryOperator::OrAssign:
|
2008-11-07 07:29:22 +08:00
|
|
|
CompTy = CheckBitwiseOperands(lhs, rhs, OpLoc, true);
|
2007-06-28 11:53:10 +08:00
|
|
|
if (!CompTy.isNull())
|
2008-11-07 07:29:22 +08:00
|
|
|
ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, 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-05 05:54:46 +08:00
|
|
|
break;
|
|
|
|
case BinaryOperator::Comma:
|
2008-11-07 07:29:22 +08:00
|
|
|
ResultTy = CheckCommaOperands(lhs, rhs, OpLoc);
|
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-05 05:54:46 +08:00
|
|
|
break;
|
|
|
|
}
|
2007-06-28 11:53:10 +08: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-05 05:54:46 +08:00
|
|
|
return true;
|
2007-06-28 11:53:10 +08:00
|
|
|
if (CompTy.isNull())
|
2008-11-07 07:29:22 +08:00
|
|
|
return new BinaryOperator(lhs, rhs, Opc, ResultTy, OpLoc);
|
2007-06-28 11:53:10 +08:00
|
|
|
else
|
2008-11-07 07:29:22 +08:00
|
|
|
return new CompoundAssignOperator(lhs, rhs, Opc, ResultTy, CompTy, OpLoc);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Binary Operators. 'Tok' is the token for the operator.
|
|
|
|
Action::ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
|
|
|
|
tok::TokenKind Kind,
|
|
|
|
ExprTy *LHS, ExprTy *RHS) {
|
|
|
|
BinaryOperator::Opcode Opc = ConvertTokenKindToBinaryOpcode(Kind);
|
|
|
|
Expr *lhs = (Expr *)LHS, *rhs = (Expr*)RHS;
|
|
|
|
|
|
|
|
assert((lhs != 0) && "ActOnBinOp(): missing left expression");
|
|
|
|
assert((rhs != 0) && "ActOnBinOp(): missing right expression");
|
|
|
|
|
2008-12-06 07:32:09 +08:00
|
|
|
// If either expression is type-dependent, just build the AST.
|
|
|
|
// FIXME: We'll need to perform some caching of the result of name
|
|
|
|
// lookup for operator+.
|
|
|
|
if (lhs->isTypeDependent() || rhs->isTypeDependent()) {
|
|
|
|
if (Opc > BinaryOperator::Assign && Opc <= BinaryOperator::OrAssign)
|
|
|
|
return new CompoundAssignOperator(lhs, rhs, Opc, Context.DependentTy,
|
|
|
|
Context.DependentTy, TokLoc);
|
|
|
|
else
|
|
|
|
return new BinaryOperator(lhs, rhs, Opc, Context.DependentTy, TokLoc);
|
|
|
|
}
|
|
|
|
|
2008-11-07 07:29:22 +08:00
|
|
|
if (getLangOptions().CPlusPlus &&
|
|
|
|
(lhs->getType()->isRecordType() || lhs->getType()->isEnumeralType() ||
|
|
|
|
rhs->getType()->isRecordType() || rhs->getType()->isEnumeralType())) {
|
Implement support for operator overloading using candidate operator
functions for built-in operators, e.g., the builtin
bool operator==(int const*, int const*)
can be used for the expression "x1 == x2" given:
struct X {
operator int const*();
} x1, x2;
The scheme for handling these built-in operators is relatively simple:
for each candidate required by the standard, create a special kind of
candidate function for the built-in. If overload resolution picks the
built-in operator, we perform the appropriate conversions on the
arguments and then let the normal built-in operator take care of it.
There may be some optimization opportunity left: if we can reduce the
number of built-in operator overloads we generate, overload resolution
for these cases will go faster. However, one must be careful when
doing this: GCC generates too few operator overloads in our little
test program, and fails to compile it because none of the overloads it
generates match.
Note that we only support operator overload for non-member binary
operators at the moment. The other operators will follow.
As part of this change, ImplicitCastExpr can now be an lvalue.
llvm-svn: 59148
2008-11-13 01:17:38 +08:00
|
|
|
// If this is one of the assignment operators, we only perform
|
|
|
|
// overload resolution if the left-hand side is a class or
|
|
|
|
// enumeration type (C++ [expr.ass]p3).
|
|
|
|
if (Opc >= BinaryOperator::Assign && Opc <= BinaryOperator::OrAssign &&
|
|
|
|
!(lhs->getType()->isRecordType() || lhs->getType()->isEnumeralType())) {
|
|
|
|
return CreateBuiltinBinOp(TokLoc, Opc, lhs, rhs);
|
|
|
|
}
|
2008-11-07 07:29:22 +08:00
|
|
|
|
|
|
|
// Determine which overloaded operator we're dealing with.
|
|
|
|
static const OverloadedOperatorKind OverOps[] = {
|
|
|
|
OO_Star, OO_Slash, OO_Percent,
|
|
|
|
OO_Plus, OO_Minus,
|
|
|
|
OO_LessLess, OO_GreaterGreater,
|
|
|
|
OO_Less, OO_Greater, OO_LessEqual, OO_GreaterEqual,
|
|
|
|
OO_EqualEqual, OO_ExclaimEqual,
|
|
|
|
OO_Amp,
|
|
|
|
OO_Caret,
|
|
|
|
OO_Pipe,
|
|
|
|
OO_AmpAmp,
|
|
|
|
OO_PipePipe,
|
|
|
|
OO_Equal, OO_StarEqual,
|
|
|
|
OO_SlashEqual, OO_PercentEqual,
|
|
|
|
OO_PlusEqual, OO_MinusEqual,
|
|
|
|
OO_LessLessEqual, OO_GreaterGreaterEqual,
|
|
|
|
OO_AmpEqual, OO_CaretEqual,
|
|
|
|
OO_PipeEqual,
|
|
|
|
OO_Comma
|
|
|
|
};
|
|
|
|
OverloadedOperatorKind OverOp = OverOps[Opc];
|
|
|
|
|
2008-11-19 07:14:02 +08:00
|
|
|
// Add the appropriate overloaded operators (C++ [over.match.oper])
|
|
|
|
// to the candidate set.
|
2008-11-19 23:42:04 +08:00
|
|
|
OverloadCandidateSet CandidateSet;
|
2008-11-07 07:29:22 +08:00
|
|
|
Expr *Args[2] = { lhs, rhs };
|
2008-11-19 07:14:02 +08:00
|
|
|
AddOperatorCandidates(OverOp, S, Args, 2, CandidateSet);
|
2008-11-07 07:29:22 +08:00
|
|
|
|
|
|
|
// Perform overload resolution.
|
|
|
|
OverloadCandidateSet::iterator Best;
|
|
|
|
switch (BestViableFunction(CandidateSet, Best)) {
|
|
|
|
case OR_Success: {
|
Implement support for operator overloading using candidate operator
functions for built-in operators, e.g., the builtin
bool operator==(int const*, int const*)
can be used for the expression "x1 == x2" given:
struct X {
operator int const*();
} x1, x2;
The scheme for handling these built-in operators is relatively simple:
for each candidate required by the standard, create a special kind of
candidate function for the built-in. If overload resolution picks the
built-in operator, we perform the appropriate conversions on the
arguments and then let the normal built-in operator take care of it.
There may be some optimization opportunity left: if we can reduce the
number of built-in operator overloads we generate, overload resolution
for these cases will go faster. However, one must be careful when
doing this: GCC generates too few operator overloads in our little
test program, and fails to compile it because none of the overloads it
generates match.
Note that we only support operator overload for non-member binary
operators at the moment. The other operators will follow.
As part of this change, ImplicitCastExpr can now be an lvalue.
llvm-svn: 59148
2008-11-13 01:17:38 +08:00
|
|
|
// We found a built-in operator or an overloaded operator.
|
2008-11-07 07:29:22 +08:00
|
|
|
FunctionDecl *FnDecl = Best->Function;
|
|
|
|
|
Implement support for operator overloading using candidate operator
functions for built-in operators, e.g., the builtin
bool operator==(int const*, int const*)
can be used for the expression "x1 == x2" given:
struct X {
operator int const*();
} x1, x2;
The scheme for handling these built-in operators is relatively simple:
for each candidate required by the standard, create a special kind of
candidate function for the built-in. If overload resolution picks the
built-in operator, we perform the appropriate conversions on the
arguments and then let the normal built-in operator take care of it.
There may be some optimization opportunity left: if we can reduce the
number of built-in operator overloads we generate, overload resolution
for these cases will go faster. However, one must be careful when
doing this: GCC generates too few operator overloads in our little
test program, and fails to compile it because none of the overloads it
generates match.
Note that we only support operator overload for non-member binary
operators at the moment. The other operators will follow.
As part of this change, ImplicitCastExpr can now be an lvalue.
llvm-svn: 59148
2008-11-13 01:17:38 +08:00
|
|
|
if (FnDecl) {
|
|
|
|
// We matched an overloaded operator. Build a call to that
|
|
|
|
// operator.
|
|
|
|
|
|
|
|
// Convert the arguments.
|
2008-11-19 07:14:02 +08:00
|
|
|
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
|
|
|
|
if (PerformObjectArgumentInitialization(lhs, Method) ||
|
|
|
|
PerformCopyInitialization(rhs, FnDecl->getParamDecl(0)->getType(),
|
|
|
|
"passing"))
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
// Convert the arguments.
|
|
|
|
if (PerformCopyInitialization(lhs, FnDecl->getParamDecl(0)->getType(),
|
|
|
|
"passing") ||
|
|
|
|
PerformCopyInitialization(rhs, FnDecl->getParamDecl(1)->getType(),
|
|
|
|
"passing"))
|
|
|
|
return true;
|
|
|
|
}
|
Implement support for operator overloading using candidate operator
functions for built-in operators, e.g., the builtin
bool operator==(int const*, int const*)
can be used for the expression "x1 == x2" given:
struct X {
operator int const*();
} x1, x2;
The scheme for handling these built-in operators is relatively simple:
for each candidate required by the standard, create a special kind of
candidate function for the built-in. If overload resolution picks the
built-in operator, we perform the appropriate conversions on the
arguments and then let the normal built-in operator take care of it.
There may be some optimization opportunity left: if we can reduce the
number of built-in operator overloads we generate, overload resolution
for these cases will go faster. However, one must be careful when
doing this: GCC generates too few operator overloads in our little
test program, and fails to compile it because none of the overloads it
generates match.
Note that we only support operator overload for non-member binary
operators at the moment. The other operators will follow.
As part of this change, ImplicitCastExpr can now be an lvalue.
llvm-svn: 59148
2008-11-13 01:17:38 +08:00
|
|
|
|
|
|
|
// Determine the result type
|
|
|
|
QualType ResultTy
|
|
|
|
= FnDecl->getType()->getAsFunctionType()->getResultType();
|
|
|
|
ResultTy = ResultTy.getNonReferenceType();
|
|
|
|
|
|
|
|
// Build the actual expression node.
|
2008-11-15 00:09:21 +08:00
|
|
|
Expr *FnExpr = new DeclRefExpr(FnDecl, FnDecl->getType(),
|
|
|
|
SourceLocation());
|
|
|
|
UsualUnaryConversions(FnExpr);
|
|
|
|
|
|
|
|
return new CXXOperatorCallExpr(FnExpr, Args, 2, ResultTy, TokLoc);
|
Implement support for operator overloading using candidate operator
functions for built-in operators, e.g., the builtin
bool operator==(int const*, int const*)
can be used for the expression "x1 == x2" given:
struct X {
operator int const*();
} x1, x2;
The scheme for handling these built-in operators is relatively simple:
for each candidate required by the standard, create a special kind of
candidate function for the built-in. If overload resolution picks the
built-in operator, we perform the appropriate conversions on the
arguments and then let the normal built-in operator take care of it.
There may be some optimization opportunity left: if we can reduce the
number of built-in operator overloads we generate, overload resolution
for these cases will go faster. However, one must be careful when
doing this: GCC generates too few operator overloads in our little
test program, and fails to compile it because none of the overloads it
generates match.
Note that we only support operator overload for non-member binary
operators at the moment. The other operators will follow.
As part of this change, ImplicitCastExpr can now be an lvalue.
llvm-svn: 59148
2008-11-13 01:17:38 +08:00
|
|
|
} else {
|
|
|
|
// We matched a built-in operator. Convert the arguments, then
|
|
|
|
// break out so that we will build the appropriate built-in
|
|
|
|
// operator node.
|
|
|
|
if (PerformCopyInitialization(lhs, Best->BuiltinTypes.ParamTypes[0],
|
|
|
|
"passing") ||
|
|
|
|
PerformCopyInitialization(rhs, Best->BuiltinTypes.ParamTypes[1],
|
|
|
|
"passing"))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2008-11-07 07:29:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
case OR_No_Viable_Function:
|
|
|
|
// No viable function; fall through to handling this as a
|
Implement support for operator overloading using candidate operator
functions for built-in operators, e.g., the builtin
bool operator==(int const*, int const*)
can be used for the expression "x1 == x2" given:
struct X {
operator int const*();
} x1, x2;
The scheme for handling these built-in operators is relatively simple:
for each candidate required by the standard, create a special kind of
candidate function for the built-in. If overload resolution picks the
built-in operator, we perform the appropriate conversions on the
arguments and then let the normal built-in operator take care of it.
There may be some optimization opportunity left: if we can reduce the
number of built-in operator overloads we generate, overload resolution
for these cases will go faster. However, one must be careful when
doing this: GCC generates too few operator overloads in our little
test program, and fails to compile it because none of the overloads it
generates match.
Note that we only support operator overload for non-member binary
operators at the moment. The other operators will follow.
As part of this change, ImplicitCastExpr can now be an lvalue.
llvm-svn: 59148
2008-11-13 01:17:38 +08:00
|
|
|
// built-in operator, which will produce an error message for us.
|
2008-11-07 07:29:22 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OR_Ambiguous:
|
2008-11-19 13:08:23 +08:00
|
|
|
Diag(TokLoc, diag::err_ovl_ambiguous_oper)
|
|
|
|
<< BinaryOperator::getOpcodeStr(Opc)
|
|
|
|
<< lhs->getSourceRange() << rhs->getSourceRange();
|
2008-11-07 07:29:22 +08:00
|
|
|
PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
Implement support for operator overloading using candidate operator
functions for built-in operators, e.g., the builtin
bool operator==(int const*, int const*)
can be used for the expression "x1 == x2" given:
struct X {
operator int const*();
} x1, x2;
The scheme for handling these built-in operators is relatively simple:
for each candidate required by the standard, create a special kind of
candidate function for the built-in. If overload resolution picks the
built-in operator, we perform the appropriate conversions on the
arguments and then let the normal built-in operator take care of it.
There may be some optimization opportunity left: if we can reduce the
number of built-in operator overloads we generate, overload resolution
for these cases will go faster. However, one must be careful when
doing this: GCC generates too few operator overloads in our little
test program, and fails to compile it because none of the overloads it
generates match.
Note that we only support operator overload for non-member binary
operators at the moment. The other operators will follow.
As part of this change, ImplicitCastExpr can now be an lvalue.
llvm-svn: 59148
2008-11-13 01:17:38 +08:00
|
|
|
// Either we found no viable overloaded operator or we matched a
|
|
|
|
// built-in operator. In either case, fall through to trying to
|
|
|
|
// build a built-in operation.
|
2008-11-07 07:29:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Build a built-in binary operation.
|
|
|
|
return CreateBuiltinBinOp(TokLoc, Opc, lhs, rhs);
|
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-05 05:54:46 +08:00
|
|
|
}
|
|
|
|
|
2007-05-07 08:24:15 +08:00
|
|
|
// Unary Operators. 'Tok' is the token for the operator.
|
2008-11-19 23:42:04 +08:00
|
|
|
Action::ExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
|
|
|
|
tok::TokenKind Op, ExprTy *input) {
|
2007-06-09 06:32:33 +08:00
|
|
|
Expr *Input = (Expr*)input;
|
2007-05-07 08:24:15 +08:00
|
|
|
UnaryOperator::Opcode Opc = ConvertTokenKindToUnaryOpcode(Op);
|
2008-11-19 23:42:04 +08:00
|
|
|
|
|
|
|
if (getLangOptions().CPlusPlus &&
|
|
|
|
(Input->getType()->isRecordType()
|
|
|
|
|| Input->getType()->isEnumeralType())) {
|
|
|
|
// Determine which overloaded operator we're dealing with.
|
|
|
|
static const OverloadedOperatorKind OverOps[] = {
|
|
|
|
OO_None, OO_None,
|
|
|
|
OO_PlusPlus, OO_MinusMinus,
|
|
|
|
OO_Amp, OO_Star,
|
|
|
|
OO_Plus, OO_Minus,
|
|
|
|
OO_Tilde, OO_Exclaim,
|
|
|
|
OO_None, OO_None,
|
|
|
|
OO_None,
|
|
|
|
OO_None
|
|
|
|
};
|
|
|
|
OverloadedOperatorKind OverOp = OverOps[Opc];
|
|
|
|
|
|
|
|
// Add the appropriate overloaded operators (C++ [over.match.oper])
|
|
|
|
// to the candidate set.
|
|
|
|
OverloadCandidateSet CandidateSet;
|
|
|
|
if (OverOp != OO_None)
|
|
|
|
AddOperatorCandidates(OverOp, S, &Input, 1, CandidateSet);
|
|
|
|
|
|
|
|
// Perform overload resolution.
|
|
|
|
OverloadCandidateSet::iterator Best;
|
|
|
|
switch (BestViableFunction(CandidateSet, Best)) {
|
|
|
|
case OR_Success: {
|
|
|
|
// We found a built-in operator or an overloaded operator.
|
|
|
|
FunctionDecl *FnDecl = Best->Function;
|
|
|
|
|
|
|
|
if (FnDecl) {
|
|
|
|
// We matched an overloaded operator. Build a call to that
|
|
|
|
// operator.
|
|
|
|
|
|
|
|
// Convert the arguments.
|
|
|
|
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
|
|
|
|
if (PerformObjectArgumentInitialization(Input, Method))
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
// Convert the arguments.
|
|
|
|
if (PerformCopyInitialization(Input,
|
|
|
|
FnDecl->getParamDecl(0)->getType(),
|
|
|
|
"passing"))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Determine the result type
|
|
|
|
QualType ResultTy
|
|
|
|
= FnDecl->getType()->getAsFunctionType()->getResultType();
|
|
|
|
ResultTy = ResultTy.getNonReferenceType();
|
|
|
|
|
|
|
|
// Build the actual expression node.
|
|
|
|
Expr *FnExpr = new DeclRefExpr(FnDecl, FnDecl->getType(),
|
|
|
|
SourceLocation());
|
|
|
|
UsualUnaryConversions(FnExpr);
|
|
|
|
|
|
|
|
return new CXXOperatorCallExpr(FnExpr, &Input, 1, ResultTy, OpLoc);
|
|
|
|
} else {
|
|
|
|
// We matched a built-in operator. Convert the arguments, then
|
|
|
|
// break out so that we will build the appropriate built-in
|
|
|
|
// operator node.
|
|
|
|
if (PerformCopyInitialization(Input, Best->BuiltinTypes.ParamTypes[0],
|
|
|
|
"passing"))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
case OR_No_Viable_Function:
|
|
|
|
// No viable function; fall through to handling this as a
|
|
|
|
// built-in operator, which will produce an error message for us.
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OR_Ambiguous:
|
|
|
|
Diag(OpLoc, diag::err_ovl_ambiguous_oper)
|
|
|
|
<< UnaryOperator::getOpcodeStr(Opc)
|
|
|
|
<< Input->getSourceRange();
|
|
|
|
PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Either we found no viable overloaded operator or we matched a
|
|
|
|
// built-in operator. In either case, fall through to trying to
|
|
|
|
// build a built-in operation.
|
|
|
|
}
|
|
|
|
|
2007-05-07 08:24:15 +08:00
|
|
|
QualType resultType;
|
|
|
|
switch (Opc) {
|
|
|
|
default:
|
|
|
|
assert(0 && "Unimplemented unary expr!");
|
|
|
|
case UnaryOperator::PreInc:
|
|
|
|
case UnaryOperator::PreDec:
|
2007-06-09 06:32:33 +08:00
|
|
|
resultType = CheckIncrementDecrementOperand(Input, OpLoc);
|
2007-05-07 08:24:15 +08:00
|
|
|
break;
|
|
|
|
case UnaryOperator::AddrOf:
|
2007-06-09 06:32:33 +08:00
|
|
|
resultType = CheckAddressOfOperand(Input, OpLoc);
|
2007-05-07 08:24:15 +08:00
|
|
|
break;
|
|
|
|
case UnaryOperator::Deref:
|
2007-12-18 12:06:57 +08:00
|
|
|
DefaultFunctionArrayConversion(Input);
|
2007-06-09 06:32:33 +08:00
|
|
|
resultType = CheckIndirectionOperand(Input, OpLoc);
|
2007-05-07 08:24:15 +08:00
|
|
|
break;
|
|
|
|
case UnaryOperator::Plus:
|
|
|
|
case UnaryOperator::Minus:
|
2007-07-17 05:54:35 +08:00
|
|
|
UsualUnaryConversions(Input);
|
|
|
|
resultType = Input->getType();
|
2008-11-19 23:42:04 +08:00
|
|
|
if (resultType->isArithmeticType()) // C99 6.5.3.3p1
|
|
|
|
break;
|
|
|
|
else if (getLangOptions().CPlusPlus && // C++ [expr.unary.op]p6-7
|
|
|
|
resultType->isEnumeralType())
|
|
|
|
break;
|
|
|
|
else if (getLangOptions().CPlusPlus && // C++ [expr.unary.op]p6
|
|
|
|
Opc == UnaryOperator::Plus &&
|
|
|
|
resultType->isPointerType())
|
|
|
|
break;
|
|
|
|
|
2008-11-20 14:06:08 +08:00
|
|
|
return Diag(OpLoc, diag::err_typecheck_unary_expr)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< resultType << Input->getSourceRange();
|
2007-05-07 08:24:15 +08:00
|
|
|
case UnaryOperator::Not: // bitwise complement
|
2007-07-17 05:54:35 +08:00
|
|
|
UsualUnaryConversions(Input);
|
|
|
|
resultType = Input->getType();
|
2008-07-26 07:52:49 +08:00
|
|
|
// C99 6.5.3.3p1. We allow complex int and float as a GCC extension.
|
|
|
|
if (resultType->isComplexType() || resultType->isComplexIntegerType())
|
|
|
|
// C99 does not support '~' for complex conjugation.
|
2008-11-20 14:06:08 +08:00
|
|
|
Diag(OpLoc, diag::ext_integer_complement_complex)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< resultType << Input->getSourceRange();
|
2008-07-26 07:52:49 +08:00
|
|
|
else if (!resultType->isIntegerType())
|
2008-11-20 14:06:08 +08:00
|
|
|
return Diag(OpLoc, diag::err_typecheck_unary_expr)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< resultType << Input->getSourceRange();
|
2007-05-07 08:24:15 +08:00
|
|
|
break;
|
|
|
|
case UnaryOperator::LNot: // logical negation
|
2007-06-05 06:22:31 +08:00
|
|
|
// Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5).
|
2007-07-17 05:54:35 +08:00
|
|
|
DefaultFunctionArrayConversion(Input);
|
|
|
|
resultType = Input->getType();
|
2007-05-07 08:24:15 +08:00
|
|
|
if (!resultType->isScalarType()) // C99 6.5.3.3p1
|
2008-11-20 14:06:08 +08:00
|
|
|
return Diag(OpLoc, diag::err_typecheck_unary_expr)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< resultType << Input->getSourceRange();
|
2007-06-03 03:11:33 +08:00
|
|
|
// LNot always has type int. C99 6.5.3.3p5.
|
|
|
|
resultType = Context.IntTy;
|
2007-05-07 08:24:15 +08:00
|
|
|
break;
|
2007-08-25 05:16:53 +08:00
|
|
|
case UnaryOperator::Real:
|
|
|
|
case UnaryOperator::Imag:
|
2007-08-25 05:41:10 +08:00
|
|
|
resultType = CheckRealImagOperand(Input, OpLoc);
|
2007-08-25 05:16:53 +08:00
|
|
|
break;
|
2007-06-09 06:32:33 +08:00
|
|
|
case UnaryOperator::Extension:
|
|
|
|
resultType = Input->getType();
|
2007-05-15 10:32:35 +08:00
|
|
|
break;
|
2007-05-07 08:24:15 +08:00
|
|
|
}
|
|
|
|
if (resultType.isNull())
|
|
|
|
return true;
|
2007-06-09 06:32:33 +08:00
|
|
|
return new UnaryOperator(Input, Opc, resultType, OpLoc);
|
2007-05-07 08:24:15 +08:00
|
|
|
}
|
2007-05-28 14:56:27 +08:00
|
|
|
|
2007-09-16 22:56:35 +08:00
|
|
|
/// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo".
|
|
|
|
Sema::ExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc,
|
2007-05-28 14:56:27 +08:00
|
|
|
SourceLocation LabLoc,
|
|
|
|
IdentifierInfo *LabelII) {
|
|
|
|
// Look up the record for this label identifier.
|
|
|
|
LabelStmt *&LabelDecl = LabelMap[LabelII];
|
|
|
|
|
2008-08-05 00:51:22 +08:00
|
|
|
// If we haven't seen this label yet, create a forward reference. It
|
|
|
|
// will be validated and/or cleaned up in ActOnFinishFunctionBody.
|
2007-05-28 14:56:27 +08:00
|
|
|
if (LabelDecl == 0)
|
|
|
|
LabelDecl = new LabelStmt(LabLoc, LabelII, 0);
|
|
|
|
|
|
|
|
// Create the AST node. The address of a label always has type 'void*'.
|
2007-08-04 01:31:20 +08:00
|
|
|
return new AddrLabelExpr(OpLoc, LabLoc, LabelDecl,
|
|
|
|
Context.getPointerType(Context.VoidTy));
|
2007-05-28 14:56:27 +08:00
|
|
|
}
|
|
|
|
|
2007-09-16 22:56:35 +08:00
|
|
|
Sema::ExprResult Sema::ActOnStmtExpr(SourceLocation LPLoc, StmtTy *substmt,
|
2007-07-25 00:58:17 +08: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;
|
|
|
|
|
2008-07-27 03:51:01 +08:00
|
|
|
if (!Compound->body_empty()) {
|
|
|
|
Stmt *LastStmt = Compound->body_back();
|
|
|
|
// If LastStmt is a label, skip down through into the body.
|
|
|
|
while (LabelStmt *Label = dyn_cast<LabelStmt>(LastStmt))
|
|
|
|
LastStmt = Label->getSubStmt();
|
|
|
|
|
|
|
|
if (Expr *LastExpr = dyn_cast<Expr>(LastStmt))
|
2007-07-25 00:58:17 +08:00
|
|
|
Ty = LastExpr->getType();
|
2008-07-27 03:51:01 +08:00
|
|
|
}
|
2007-07-25 00:58:17 +08:00
|
|
|
|
|
|
|
return new StmtExpr(Compound, Ty, LPLoc, RPLoc);
|
|
|
|
}
|
2007-08-02 06:05:33 +08:00
|
|
|
|
2007-09-16 22:56:35 +08:00
|
|
|
Sema::ExprResult Sema::ActOnBuiltinOffsetOf(SourceLocation BuiltinLoc,
|
2007-08-31 01:45:32 +08: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())
|
2008-11-24 14:25:27 +08:00
|
|
|
return Diag(TypeLoc, diag::err_offsetof_record_type) << ArgTy;
|
2007-08-31 01:45:32 +08:00
|
|
|
|
|
|
|
// Otherwise, create a compound literal expression as the base, and
|
|
|
|
// iteratively process the offsetof designators.
|
2008-01-15 02:19:28 +08:00
|
|
|
Expr *Res = new CompoundLiteralExpr(SourceLocation(), ArgTy, 0, false);
|
2007-08-31 01:45:32 +08:00
|
|
|
|
2007-09-01 05:49:13 +08:00
|
|
|
// offsetof with non-identifier designators (e.g. "offsetof(x, a.b[c])") are a
|
|
|
|
// GCC extension, diagnose them.
|
|
|
|
if (NumComponents != 1)
|
2008-11-19 13:27:50 +08:00
|
|
|
Diag(BuiltinLoc, diag::ext_offsetof_extended_field_designator)
|
|
|
|
<< SourceRange(CompPtr[1].LocStart, CompPtr[NumComponents-1].LocEnd);
|
2007-09-01 05:49:13 +08:00
|
|
|
|
2007-08-31 01:45:32 +08: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?
|
2008-08-04 15:31:14 +08:00
|
|
|
const ArrayType *AT = Context.getAsArrayType(Res->getType());
|
2007-08-31 01:45:32 +08:00
|
|
|
if (!AT) {
|
|
|
|
delete Res;
|
2008-11-24 14:25:27 +08:00
|
|
|
return Diag(OC.LocEnd, diag::err_offsetof_array_type) << Res->getType();
|
2007-08-31 01:45:32 +08:00
|
|
|
}
|
|
|
|
|
2007-08-31 01:59:59 +08:00
|
|
|
// FIXME: C++: Verify that operator[] isn't overloaded.
|
|
|
|
|
2007-08-31 01:45:32 +08:00
|
|
|
// C99 6.5.2.1p1
|
|
|
|
Expr *Idx = static_cast<Expr*>(OC.U.E);
|
|
|
|
if (!Idx->getType()->isIntegerType())
|
2008-11-19 13:27:50 +08:00
|
|
|
return Diag(Idx->getLocStart(), diag::err_typecheck_subscript)
|
|
|
|
<< Idx->getSourceRange();
|
2007-08-31 01:45:32 +08:00
|
|
|
|
|
|
|
Res = new ArraySubscriptExpr(Res, Idx, AT->getElementType(), OC.LocEnd);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
const RecordType *RC = Res->getType()->getAsRecordType();
|
|
|
|
if (!RC) {
|
|
|
|
delete Res;
|
2008-11-24 14:25:27 +08:00
|
|
|
return Diag(OC.LocEnd, diag::err_offsetof_record_type) << Res->getType();
|
2007-08-31 01:45:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Get the decl corresponding to this.
|
|
|
|
RecordDecl *RD = RC->getDecl();
|
2008-12-12 00:49:14 +08:00
|
|
|
FieldDecl *MemberDecl = 0;
|
|
|
|
DeclContext::lookup_result Lookup = RD->lookup(Context, OC.U.IdentInfo);
|
|
|
|
if (Lookup.first != Lookup.second)
|
|
|
|
MemberDecl = dyn_cast<FieldDecl>(*Lookup.first);
|
|
|
|
|
2007-08-31 01:45:32 +08:00
|
|
|
if (!MemberDecl)
|
2008-11-19 16:23:25 +08:00
|
|
|
return Diag(BuiltinLoc, diag::err_typecheck_no_member)
|
|
|
|
<< OC.U.IdentInfo << SourceRange(OC.LocStart, OC.LocEnd);
|
2007-08-31 01:59:59 +08:00
|
|
|
|
|
|
|
// FIXME: C++: Verify that MemberDecl isn't a static field.
|
|
|
|
// FIXME: Verify that MemberDecl isn't a bitfield.
|
2008-02-07 06:48:16 +08:00
|
|
|
// MemberDecl->getType() doesn't get the right qualifiers, but it doesn't
|
|
|
|
// matter here.
|
2008-10-28 08:22:11 +08:00
|
|
|
Res = new MemberExpr(Res, false, MemberDecl, OC.LocEnd,
|
|
|
|
MemberDecl->getType().getNonReferenceType());
|
2007-08-31 01:45:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return new UnaryOperator(Res, UnaryOperator::OffsetOf, Context.getSizeType(),
|
|
|
|
BuiltinLoc);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-09-16 22:56:35 +08:00
|
|
|
Sema::ExprResult Sema::ActOnTypesCompatibleExpr(SourceLocation BuiltinLoc,
|
2007-08-02 06:05:33 +08: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-31 01:45:32 +08:00
|
|
|
return new TypesCompatibleExpr(Context.IntTy, BuiltinLoc, argT1, argT2,RPLoc);
|
2007-08-02 06:05:33 +08:00
|
|
|
}
|
|
|
|
|
2007-09-16 22:56:35 +08:00
|
|
|
Sema::ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc, ExprTy *cond,
|
2007-08-04 05:21:27 +08: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))
|
2008-11-19 13:27:50 +08:00
|
|
|
return Diag(ExpLoc, diag::err_typecheck_choose_expr_requires_constant)
|
|
|
|
<< CondExpr->getSourceRange();
|
2007-08-04 05:21:27 +08:00
|
|
|
|
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
|
2008-09-04 02:15:37 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Clang Extensions.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
/// ActOnBlockStart - This callback is invoked when a block literal is started.
|
2008-10-10 09:28:17 +08:00
|
|
|
void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *BlockScope) {
|
2008-09-04 02:15:37 +08:00
|
|
|
// Analyze block parameters.
|
|
|
|
BlockSemaInfo *BSI = new BlockSemaInfo();
|
|
|
|
|
|
|
|
// Add BSI to CurBlock.
|
|
|
|
BSI->PrevBlockInfo = CurBlock;
|
|
|
|
CurBlock = BSI;
|
|
|
|
|
|
|
|
BSI->ReturnType = 0;
|
|
|
|
BSI->TheScope = BlockScope;
|
|
|
|
|
2008-10-10 09:28:17 +08:00
|
|
|
BSI->TheDecl = BlockDecl::Create(Context, CurContext, CaretLoc);
|
2008-12-12 00:49:14 +08:00
|
|
|
PushDeclContext(BlockScope, BSI->TheDecl);
|
2008-10-10 09:28:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void Sema::ActOnBlockArguments(Declarator &ParamInfo) {
|
2008-09-04 02:15:37 +08:00
|
|
|
// Analyze arguments to block.
|
|
|
|
assert(ParamInfo.getTypeObject(0).Kind == DeclaratorChunk::Function &&
|
|
|
|
"Not a function declarator!");
|
|
|
|
DeclaratorChunk::FunctionTypeInfo &FTI = ParamInfo.getTypeObject(0).Fun;
|
|
|
|
|
2008-10-10 09:28:17 +08:00
|
|
|
CurBlock->hasPrototype = FTI.hasPrototype;
|
|
|
|
CurBlock->isVariadic = true;
|
2008-09-04 02:15:37 +08:00
|
|
|
|
|
|
|
// Check for C99 6.7.5.3p10 - foo(void) is a non-varargs function that takes
|
|
|
|
// no arguments, not a function that takes a single void argument.
|
|
|
|
if (FTI.hasPrototype &&
|
|
|
|
FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
|
|
|
|
(!((ParmVarDecl *)FTI.ArgInfo[0].Param)->getType().getCVRQualifiers() &&
|
|
|
|
((ParmVarDecl *)FTI.ArgInfo[0].Param)->getType()->isVoidType())) {
|
|
|
|
// empty arg list, don't push any params.
|
2008-10-10 09:28:17 +08:00
|
|
|
CurBlock->isVariadic = false;
|
2008-09-04 02:15:37 +08:00
|
|
|
} else if (FTI.hasPrototype) {
|
|
|
|
for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i)
|
2008-10-10 09:28:17 +08:00
|
|
|
CurBlock->Params.push_back((ParmVarDecl *)FTI.ArgInfo[i].Param);
|
|
|
|
CurBlock->isVariadic = FTI.isVariadic;
|
2008-09-04 02:15:37 +08:00
|
|
|
}
|
2008-10-10 09:28:17 +08:00
|
|
|
CurBlock->TheDecl->setArgs(&CurBlock->Params[0], CurBlock->Params.size());
|
|
|
|
|
|
|
|
for (BlockDecl::param_iterator AI = CurBlock->TheDecl->param_begin(),
|
|
|
|
E = CurBlock->TheDecl->param_end(); AI != E; ++AI)
|
|
|
|
// If this has an identifier, add it to the scope stack.
|
|
|
|
if ((*AI)->getIdentifier())
|
|
|
|
PushOnScopeChains(*AI, CurBlock->TheScope);
|
2008-09-04 02:15:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// ActOnBlockError - If there is an error parsing a block, this callback
|
|
|
|
/// is invoked to pop the information about the block from the action impl.
|
|
|
|
void Sema::ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) {
|
|
|
|
// Ensure that CurBlock is deleted.
|
|
|
|
llvm::OwningPtr<BlockSemaInfo> CC(CurBlock);
|
|
|
|
|
|
|
|
// Pop off CurBlock, handle nested blocks.
|
|
|
|
CurBlock = CurBlock->PrevBlockInfo;
|
|
|
|
|
|
|
|
// FIXME: Delete the ParmVarDecl objects as well???
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ActOnBlockStmtExpr - This is called when the body of a block statement
|
|
|
|
/// literal was successfully completed. ^(int x){...}
|
|
|
|
Sema::ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, StmtTy *body,
|
|
|
|
Scope *CurScope) {
|
|
|
|
// Ensure that CurBlock is deleted.
|
|
|
|
llvm::OwningPtr<BlockSemaInfo> BSI(CurBlock);
|
|
|
|
llvm::OwningPtr<CompoundStmt> Body(static_cast<CompoundStmt*>(body));
|
|
|
|
|
2008-10-10 09:28:17 +08:00
|
|
|
PopDeclContext();
|
|
|
|
|
2008-09-04 02:15:37 +08:00
|
|
|
// Pop off CurBlock, handle nested blocks.
|
|
|
|
CurBlock = CurBlock->PrevBlockInfo;
|
|
|
|
|
|
|
|
QualType RetTy = Context.VoidTy;
|
|
|
|
if (BSI->ReturnType)
|
|
|
|
RetTy = QualType(BSI->ReturnType, 0);
|
|
|
|
|
|
|
|
llvm::SmallVector<QualType, 8> ArgTypes;
|
|
|
|
for (unsigned i = 0, e = BSI->Params.size(); i != e; ++i)
|
|
|
|
ArgTypes.push_back(BSI->Params[i]->getType());
|
|
|
|
|
|
|
|
QualType BlockTy;
|
|
|
|
if (!BSI->hasPrototype)
|
|
|
|
BlockTy = Context.getFunctionTypeNoProto(RetTy);
|
|
|
|
else
|
|
|
|
BlockTy = Context.getFunctionType(RetTy, &ArgTypes[0], ArgTypes.size(),
|
2008-10-27 00:43:14 +08:00
|
|
|
BSI->isVariadic, 0);
|
2008-09-04 02:15:37 +08:00
|
|
|
|
|
|
|
BlockTy = Context.getBlockPointerType(BlockTy);
|
2008-10-09 01:01:13 +08:00
|
|
|
|
2008-10-09 02:44:00 +08:00
|
|
|
BSI->TheDecl->setBody(Body.take());
|
|
|
|
return new BlockExpr(BSI->TheDecl, BlockTy);
|
2008-09-04 02:15:37 +08:00
|
|
|
}
|
|
|
|
|
2008-01-31 04:50:20 +08:00
|
|
|
/// ExprsMatchFnType - return true if the Exprs in array Args have
|
2008-01-18 01:46:27 +08:00
|
|
|
/// QualTypes that match the QualTypes of the arguments of the FnType.
|
2008-01-31 04:50:20 +08:00
|
|
|
/// The number of arguments has already been validated to match the number of
|
|
|
|
/// arguments in FnType.
|
2008-07-27 06:17:49 +08:00
|
|
|
static bool ExprsMatchFnType(Expr **Args, const FunctionTypeProto *FnType,
|
|
|
|
ASTContext &Context) {
|
2008-01-18 01:46:27 +08:00
|
|
|
unsigned NumParams = FnType->getNumArgs();
|
2008-04-19 07:35:14 +08:00
|
|
|
for (unsigned i = 0; i != NumParams; ++i) {
|
2008-07-27 06:17:49 +08:00
|
|
|
QualType ExprTy = Context.getCanonicalType(Args[i]->getType());
|
|
|
|
QualType ParmTy = Context.getCanonicalType(FnType->getArgType(i));
|
2008-04-19 07:35:14 +08:00
|
|
|
|
|
|
|
if (ExprTy.getUnqualifiedType() != ParmTy.getUnqualifiedType())
|
2008-01-18 01:46:27 +08:00
|
|
|
return false;
|
2008-04-19 07:35:14 +08:00
|
|
|
}
|
2008-01-18 01:46:27 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
Sema::ExprResult Sema::ActOnOverloadExpr(ExprTy **args, unsigned NumArgs,
|
|
|
|
SourceLocation *CommaLocs,
|
|
|
|
SourceLocation BuiltinLoc,
|
|
|
|
SourceLocation RParenLoc) {
|
2008-01-31 13:38:29 +08:00
|
|
|
// __builtin_overload requires at least 2 arguments
|
|
|
|
if (NumArgs < 2)
|
2008-11-19 13:27:50 +08:00
|
|
|
return Diag(RParenLoc, diag::err_typecheck_call_too_few_args)
|
|
|
|
<< SourceRange(BuiltinLoc, RParenLoc);
|
2008-01-18 01:46:27 +08:00
|
|
|
|
|
|
|
// The first argument is required to be a constant expression. It tells us
|
|
|
|
// the number of arguments to pass to each of the functions to be overloaded.
|
2008-01-31 13:38:29 +08:00
|
|
|
Expr **Args = reinterpret_cast<Expr**>(args);
|
2008-01-18 01:46:27 +08:00
|
|
|
Expr *NParamsExpr = Args[0];
|
|
|
|
llvm::APSInt constEval(32);
|
|
|
|
SourceLocation ExpLoc;
|
|
|
|
if (!NParamsExpr->isIntegerConstantExpr(constEval, Context, &ExpLoc))
|
2008-11-19 13:27:50 +08:00
|
|
|
return Diag(ExpLoc, diag::err_overload_expr_requires_non_zero_constant)
|
|
|
|
<< NParamsExpr->getSourceRange();
|
2008-01-18 01:46:27 +08:00
|
|
|
|
|
|
|
// Verify that the number of parameters is > 0
|
|
|
|
unsigned NumParams = constEval.getZExtValue();
|
|
|
|
if (NumParams == 0)
|
2008-11-19 13:27:50 +08:00
|
|
|
return Diag(ExpLoc, diag::err_overload_expr_requires_non_zero_constant)
|
|
|
|
<< NParamsExpr->getSourceRange();
|
2008-01-18 01:46:27 +08:00
|
|
|
// Verify that we have at least 1 + NumParams arguments to the builtin.
|
|
|
|
if ((NumParams + 1) > NumArgs)
|
2008-11-19 13:27:50 +08:00
|
|
|
return Diag(RParenLoc, diag::err_typecheck_call_too_few_args)
|
|
|
|
<< SourceRange(BuiltinLoc, RParenLoc);
|
2008-01-18 01:46:27 +08:00
|
|
|
|
|
|
|
// Figure out the return type, by matching the args to one of the functions
|
2008-01-31 04:50:20 +08:00
|
|
|
// listed after the parameters.
|
2008-01-31 13:38:29 +08:00
|
|
|
OverloadExpr *OE = 0;
|
2008-01-18 01:46:27 +08:00
|
|
|
for (unsigned i = NumParams + 1; i < NumArgs; ++i) {
|
|
|
|
// UsualUnaryConversions will convert the function DeclRefExpr into a
|
|
|
|
// pointer to function.
|
|
|
|
Expr *Fn = UsualUnaryConversions(Args[i]);
|
2008-07-27 06:17:49 +08:00
|
|
|
const FunctionTypeProto *FnType = 0;
|
|
|
|
if (const PointerType *PT = Fn->getType()->getAsPointerType())
|
|
|
|
FnType = PT->getPointeeType()->getAsFunctionTypeProto();
|
2008-01-18 01:46:27 +08:00
|
|
|
|
|
|
|
// The Expr type must be FunctionTypeProto, since FunctionTypeProto has no
|
|
|
|
// parameters, and the number of parameters must match the value passed to
|
|
|
|
// the builtin.
|
|
|
|
if (!FnType || (FnType->getNumArgs() != NumParams))
|
2008-11-19 13:27:50 +08:00
|
|
|
return Diag(Fn->getExprLoc(), diag::err_overload_incorrect_fntype)
|
|
|
|
<< Fn->getSourceRange();
|
2008-01-18 01:46:27 +08:00
|
|
|
|
|
|
|
// Scan the parameter list for the FunctionType, checking the QualType of
|
2008-01-31 04:50:20 +08:00
|
|
|
// each parameter against the QualTypes of the arguments to the builtin.
|
2008-01-18 01:46:27 +08:00
|
|
|
// If they match, return a new OverloadExpr.
|
2008-07-27 06:17:49 +08:00
|
|
|
if (ExprsMatchFnType(Args+1, FnType, Context)) {
|
2008-01-31 13:38:29 +08:00
|
|
|
if (OE)
|
2008-11-19 13:27:50 +08:00
|
|
|
return Diag(Fn->getExprLoc(), diag::err_overload_multiple_match)
|
|
|
|
<< OE->getFn()->getSourceRange();
|
2008-01-31 13:38:29 +08:00
|
|
|
// Remember our match, and continue processing the remaining arguments
|
|
|
|
// to catch any errors.
|
2008-10-28 08:22:11 +08:00
|
|
|
OE = new OverloadExpr(Args, NumArgs, i,
|
|
|
|
FnType->getResultType().getNonReferenceType(),
|
2008-01-31 13:38:29 +08:00
|
|
|
BuiltinLoc, RParenLoc);
|
|
|
|
}
|
2008-01-18 01:46:27 +08:00
|
|
|
}
|
2008-01-31 13:38:29 +08:00
|
|
|
// Return the newly created OverloadExpr node, if we succeded in matching
|
|
|
|
// exactly one of the candidate functions.
|
|
|
|
if (OE)
|
|
|
|
return OE;
|
2008-01-18 01:46:27 +08:00
|
|
|
|
|
|
|
// If we didn't find a matching function Expr in the __builtin_overload list
|
|
|
|
// the return an error.
|
|
|
|
std::string typeNames;
|
2008-01-31 04:50:20 +08:00
|
|
|
for (unsigned i = 0; i != NumParams; ++i) {
|
|
|
|
if (i != 0) typeNames += ", ";
|
|
|
|
typeNames += Args[i+1]->getType().getAsString();
|
|
|
|
}
|
2008-01-18 01:46:27 +08:00
|
|
|
|
2008-11-20 14:06:08 +08:00
|
|
|
return Diag(BuiltinLoc, diag::err_overload_no_match)
|
|
|
|
<< typeNames << SourceRange(BuiltinLoc, RParenLoc);
|
2008-01-18 01:46:27 +08:00
|
|
|
}
|
|
|
|
|
2007-10-16 04:28:48 +08:00
|
|
|
Sema::ExprResult Sema::ActOnVAArg(SourceLocation BuiltinLoc,
|
|
|
|
ExprTy *expr, TypeTy *type,
|
2008-01-05 02:04:52 +08:00
|
|
|
SourceLocation RPLoc) {
|
2007-10-16 04:28:48 +08:00
|
|
|
Expr *E = static_cast<Expr*>(expr);
|
|
|
|
QualType T = QualType::getFromOpaquePtr(type);
|
|
|
|
|
|
|
|
InitBuiltinVaListType();
|
2008-08-10 07:32:40 +08:00
|
|
|
|
|
|
|
// Get the va_list type
|
|
|
|
QualType VaListType = Context.getBuiltinVaListType();
|
|
|
|
// Deal with implicit array decay; for example, on x86-64,
|
|
|
|
// va_list is an array, but it's supposed to decay to
|
|
|
|
// a pointer for va_arg.
|
|
|
|
if (VaListType->isArrayType())
|
|
|
|
VaListType = Context.getArrayDecayedType(VaListType);
|
2008-08-21 06:17:17 +08:00
|
|
|
// Make sure the input expression also decays appropriately.
|
|
|
|
UsualUnaryConversions(E);
|
2008-08-10 07:32:40 +08:00
|
|
|
|
|
|
|
if (CheckAssignmentConstraints(VaListType, E->getType()) != Compatible)
|
2007-10-16 04:28:48 +08:00
|
|
|
return Diag(E->getLocStart(),
|
2008-11-20 14:06:08 +08:00
|
|
|
diag::err_first_argument_to_va_arg_not_of_type_va_list)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< E->getType() << E->getSourceRange();
|
2007-10-16 04:28:48 +08:00
|
|
|
|
|
|
|
// FIXME: Warn if a non-POD type is passed in.
|
|
|
|
|
2008-10-28 08:22:11 +08:00
|
|
|
return new VAArgExpr(BuiltinLoc, E, T.getNonReferenceType(), RPLoc);
|
2007-10-16 04:28:48 +08:00
|
|
|
}
|
|
|
|
|
2008-11-29 12:51:27 +08:00
|
|
|
Sema::ExprResult Sema::ActOnGNUNullExpr(SourceLocation TokenLoc) {
|
|
|
|
// The type of __null will be int or long, depending on the size of
|
|
|
|
// pointers on the target.
|
|
|
|
QualType Ty;
|
|
|
|
if (Context.Target.getPointerWidth(0) == Context.Target.getIntWidth())
|
|
|
|
Ty = Context.IntTy;
|
|
|
|
else
|
|
|
|
Ty = Context.LongTy;
|
|
|
|
|
|
|
|
return new GNUNullExpr(Ty, TokenLoc);
|
|
|
|
}
|
|
|
|
|
2008-01-05 02:04:52 +08:00
|
|
|
bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
|
|
|
|
SourceLocation Loc,
|
|
|
|
QualType DstType, QualType SrcType,
|
|
|
|
Expr *SrcExpr, const char *Flavor) {
|
|
|
|
// Decode the result (notice that AST's are still created for extensions).
|
|
|
|
bool isInvalid = false;
|
|
|
|
unsigned DiagKind;
|
|
|
|
switch (ConvTy) {
|
|
|
|
default: assert(0 && "Unknown conversion type");
|
|
|
|
case Compatible: return false;
|
2008-01-05 02:22:42 +08:00
|
|
|
case PointerToInt:
|
2008-01-05 02:04:52 +08:00
|
|
|
DiagKind = diag::ext_typecheck_convert_pointer_int;
|
|
|
|
break;
|
2008-01-05 02:22:42 +08:00
|
|
|
case IntToPointer:
|
|
|
|
DiagKind = diag::ext_typecheck_convert_int_pointer;
|
|
|
|
break;
|
2008-01-05 02:04:52 +08:00
|
|
|
case IncompatiblePointer:
|
|
|
|
DiagKind = diag::ext_typecheck_convert_incompatible_pointer;
|
|
|
|
break;
|
|
|
|
case FunctionVoidPointer:
|
|
|
|
DiagKind = diag::ext_typecheck_convert_pointer_void_func;
|
|
|
|
break;
|
|
|
|
case CompatiblePointerDiscardsQualifiers:
|
2008-09-12 08:47:35 +08:00
|
|
|
// If the qualifiers lost were because we were applying the
|
|
|
|
// (deprecated) C++ conversion from a string literal to a char*
|
|
|
|
// (or wchar_t*), then there was no error (C++ 4.2p2). FIXME:
|
|
|
|
// Ideally, this check would be performed in
|
|
|
|
// CheckPointerTypesForAssignment. However, that would require a
|
|
|
|
// bit of refactoring (so that the second argument is an
|
|
|
|
// expression, rather than a type), which should be done as part
|
|
|
|
// of a larger effort to fix CheckPointerTypesForAssignment for
|
|
|
|
// C++ semantics.
|
|
|
|
if (getLangOptions().CPlusPlus &&
|
|
|
|
IsStringLiteralToNonConstPointerConversion(SrcExpr, DstType))
|
|
|
|
return false;
|
2008-01-05 02:04:52 +08:00
|
|
|
DiagKind = diag::ext_typecheck_convert_discards_qualifiers;
|
|
|
|
break;
|
2008-09-04 23:10:53 +08:00
|
|
|
case IntToBlockPointer:
|
|
|
|
DiagKind = diag::err_int_to_block_pointer;
|
|
|
|
break;
|
|
|
|
case IncompatibleBlockPointer:
|
2008-09-25 07:31:10 +08:00
|
|
|
DiagKind = diag::ext_typecheck_convert_incompatible_block_pointer;
|
2008-09-04 23:10:53 +08:00
|
|
|
break;
|
2008-10-15 06:18:38 +08:00
|
|
|
case IncompatibleObjCQualifiedId:
|
|
|
|
// FIXME: Diagnose the problem in ObjCQualifiedIdTypesAreCompatible, since
|
|
|
|
// it can give a more specific diagnostic.
|
|
|
|
DiagKind = diag::warn_incompatible_qualified_id;
|
|
|
|
break;
|
2008-01-05 02:04:52 +08:00
|
|
|
case Incompatible:
|
|
|
|
DiagKind = diag::err_typecheck_convert_incompatible;
|
|
|
|
isInvalid = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-11-24 13:29:24 +08:00
|
|
|
Diag(Loc, DiagKind) << DstType << SrcType << Flavor
|
|
|
|
<< SrcExpr->getSourceRange();
|
2008-01-05 02:04:52 +08:00
|
|
|
return isInvalid;
|
|
|
|
}
|
2008-12-01 03:50:32 +08:00
|
|
|
|
|
|
|
bool Sema::VerifyIntegerConstantExpression(const Expr* E, llvm::APSInt *Result)
|
|
|
|
{
|
|
|
|
Expr::EvalResult EvalResult;
|
|
|
|
|
|
|
|
if (!E->Evaluate(EvalResult, Context) || !EvalResult.Val.isInt() ||
|
|
|
|
EvalResult.HasSideEffects) {
|
|
|
|
Diag(E->getExprLoc(), diag::err_expr_not_ice) << E->getSourceRange();
|
|
|
|
|
|
|
|
if (EvalResult.Diag) {
|
|
|
|
// We only show the note if it's not the usual "invalid subexpression"
|
|
|
|
// or if it's actually in a subexpression.
|
|
|
|
if (EvalResult.Diag != diag::note_invalid_subexpr_in_ice ||
|
|
|
|
E->IgnoreParens() != EvalResult.DiagExpr->IgnoreParens())
|
|
|
|
Diag(EvalResult.DiagLoc, EvalResult.Diag);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (EvalResult.Diag) {
|
|
|
|
Diag(E->getExprLoc(), diag::ext_expr_not_ice) <<
|
|
|
|
E->getSourceRange();
|
|
|
|
|
|
|
|
// Print the reason it's not a constant.
|
|
|
|
if (Diags.getDiagnosticLevel(diag::ext_expr_not_ice) != Diagnostic::Ignored)
|
|
|
|
Diag(EvalResult.DiagLoc, EvalResult.Diag);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Result)
|
|
|
|
*Result = EvalResult.Val.getInt();
|
|
|
|
return false;
|
|
|
|
}
|