summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaExpr.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2008-03-15 23:59:48 +0000
committerChris Lattner <sabre@nondot.org>2008-03-15 23:59:48 +0000
commit7a51313d8a0a358bb92eb5dbf8fd846b7c48e7fe (patch)
treef34d8e560a6abbae809b7dbee85606becf47dfd0 /clang/lib/Sema/SemaExpr.cpp
parentd3f989ccd302d53e327c030347313fbd8d23a344 (diff)
downloadbcm5719-llvm-7a51313d8a0a358bb92eb5dbf8fd846b7c48e7fe.tar.gz
bcm5719-llvm-7a51313d8a0a358bb92eb5dbf8fd846b7c48e7fe.zip
Make a major restructuring of the clang tree: introduce a top-level
lib dir and move all the libraries into it. This follows the main llvm tree, and allows the libraries to be built in parallel. The top level now enforces that all the libs are built before Driver, but we don't care what order the libs are built in. This speeds up parallel builds, particularly incremental ones. llvm-svn: 48402
Diffstat (limited to 'clang/lib/Sema/SemaExpr.cpp')
-rw-r--r--clang/lib/Sema/SemaExpr.cpp2286
1 files changed, 2286 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
new file mode 100644
index 00000000000..d756345c1a8
--- /dev/null
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -0,0 +1,2286 @@
+//===--- SemaExpr.cpp - Semantic Analysis for Expressions -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements semantic analysis for expressions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "SemaUtil.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Expr.h"
+#include "clang/Parse/DeclSpec.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/LiteralSupport.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+using namespace clang;
+
+/// ActOnStringLiteral - The specified tokens were lexed as pasted string
+/// fragments (e.g. "foo" "bar" L"baz"). The result string has to handle string
+/// concatenation ([C99 5.1.1.2, translation phase #6]), so it may come from
+/// multiple tokens. However, the common case is that StringToks points to one
+/// string.
+///
+Action::ExprResult
+Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) {
+ assert(NumStringToks && "Must have at least one string!");
+
+ StringLiteralParser Literal(StringToks, NumStringToks, PP, Context.Target);
+ if (Literal.hadError)
+ return ExprResult(true);
+
+ llvm::SmallVector<SourceLocation, 4> StringTokLocs;
+ for (unsigned i = 0; i != NumStringToks; ++i)
+ StringTokLocs.push_back(StringToks[i].getLocation());
+
+ // Verify that pascal strings aren't too large.
+ if (Literal.Pascal && Literal.GetStringLength() > 256)
+ return Diag(StringToks[0].getLocation(), diag::err_pascal_string_too_long,
+ SourceRange(StringToks[0].getLocation(),
+ StringToks[NumStringToks-1].getLocation()));
+
+ QualType StrTy = Context.CharTy;
+ // FIXME: handle wchar_t
+ if (Literal.Pascal) StrTy = Context.UnsignedCharTy;
+
+ // Get an array type for the string, according to C99 6.4.5. This includes
+ // the nul terminator character as well as the string length for pascal
+ // strings.
+ StrTy = Context.getConstantArrayType(StrTy,
+ llvm::APInt(32, Literal.GetStringLength()+1),
+ ArrayType::Normal, 0);
+
+ // Pass &StringTokLocs[0], StringTokLocs.size() to factory!
+ return new StringLiteral(Literal.GetString(), Literal.GetStringLength(),
+ Literal.AnyWide, StrTy,
+ StringToks[0].getLocation(),
+ StringToks[NumStringToks-1].getLocation());
+}
+
+
+/// ActOnIdentifierExpr - The parser read an identifier in expression context,
+/// validate it per-C99 6.5.1. HasTrailingLParen indicates whether this
+/// identifier is used in an function call context.
+Sema::ExprResult Sema::ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
+ IdentifierInfo &II,
+ bool HasTrailingLParen) {
+ // Could be enum-constant or decl.
+ ScopedDecl *D = LookupScopedDecl(&II, Decl::IDNS_Ordinary, Loc, S);
+ if (D == 0) {
+ // Otherwise, this could be an implicitly declared function reference (legal
+ // in C90, extension in C99).
+ if (HasTrailingLParen &&
+ // Not in C++.
+ !getLangOptions().CPlusPlus)
+ D = ImplicitlyDefineFunction(Loc, II, S);
+ else {
+ if (CurMethodDecl) {
+ ObjCInterfaceDecl *IFace = CurMethodDecl->getClassInterface();
+ ObjCInterfaceDecl *clsDeclared;
+ if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(&II, clsDeclared)) {
+ IdentifierInfo &II = Context.Idents.get("self");
+ ExprResult SelfExpr = ActOnIdentifierExpr(S, Loc, II, false);
+ return new ObjCIvarRefExpr(IV, IV->getType(), Loc,
+ static_cast<Expr*>(SelfExpr.Val), true, true);
+ }
+ }
+ // If this name wasn't predeclared and if this is not a function call,
+ // diagnose the problem.
+ return Diag(Loc, diag::err_undeclared_var_use, II.getName());
+ }
+ }
+ if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
+ // check if referencing an identifier with __attribute__((deprecated)).
+ if (VD->getAttr<DeprecatedAttr>())
+ Diag(Loc, diag::warn_deprecated, VD->getName());
+
+ // Only create DeclRefExpr's for valid Decl's.
+ if (VD->isInvalidDecl())
+ return true;
+ return new DeclRefExpr(VD, VD->getType(), Loc);
+ }
+ if (isa<TypedefDecl>(D))
+ return Diag(Loc, diag::err_unexpected_typedef, II.getName());
+ if (isa<ObjCInterfaceDecl>(D))
+ return Diag(Loc, diag::err_unexpected_interface, II.getName());
+
+ assert(0 && "Invalid decl");
+ abort();
+}
+
+Sema::ExprResult Sema::ActOnPreDefinedExpr(SourceLocation Loc,
+ tok::TokenKind Kind) {
+ PreDefinedExpr::IdentType IT;
+
+ switch (Kind) {
+ default: assert(0 && "Unknown simple primary expr!");
+ case tok::kw___func__: IT = PreDefinedExpr::Func; break; // [C99 6.4.2.2]
+ case tok::kw___FUNCTION__: IT = PreDefinedExpr::Function; break;
+ case tok::kw___PRETTY_FUNCTION__: IT = PreDefinedExpr::PrettyFunction; break;
+ }
+
+ // Verify that this is in a function context.
+ if (CurFunctionDecl == 0 && CurMethodDecl == 0)
+ return Diag(Loc, diag::err_predef_outside_function);
+
+ // Pre-defined identifiers are of type char[x], where x is the length of the
+ // string.
+ unsigned Length;
+ if (CurFunctionDecl)
+ Length = CurFunctionDecl->getIdentifier()->getLength();
+ else
+ Length = CurMethodDecl->getSynthesizedMethodSize();
+
+ llvm::APInt LengthI(32, Length + 1);
+ QualType ResTy = Context.CharTy.getQualifiedType(QualType::Const);
+ ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0);
+ return new PreDefinedExpr(Loc, ResTy, IT);
+}
+
+Sema::ExprResult Sema::ActOnCharacterConstant(const Token &Tok) {
+ llvm::SmallString<16> CharBuffer;
+ CharBuffer.resize(Tok.getLength());
+ const char *ThisTokBegin = &CharBuffer[0];
+ unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin);
+
+ CharLiteralParser Literal(ThisTokBegin, ThisTokBegin+ActualLength,
+ Tok.getLocation(), PP);
+ if (Literal.hadError())
+ return ExprResult(true);
+
+ QualType type = getLangOptions().CPlusPlus ? Context.CharTy : Context.IntTy;
+
+ return new CharacterLiteral(Literal.getValue(), type, Tok.getLocation());
+}
+
+Action::ExprResult Sema::ActOnNumericConstant(const Token &Tok) {
+ // fast path for a single digit (which is quite common). A single digit
+ // cannot have a trigraph, escaped newline, radix prefix, or type suffix.
+ if (Tok.getLength() == 1) {
+ const char *t = PP.getSourceManager().getCharacterData(Tok.getLocation());
+
+ unsigned IntSize =static_cast<unsigned>(Context.getTypeSize(Context.IntTy));
+ return ExprResult(new IntegerLiteral(llvm::APInt(IntSize, *t-'0'),
+ Context.IntTy,
+ Tok.getLocation()));
+ }
+ llvm::SmallString<512> IntegerBuffer;
+ IntegerBuffer.resize(Tok.getLength());
+ const char *ThisTokBegin = &IntegerBuffer[0];
+
+ // Get the spelling of the token, which eliminates trigraphs, etc.
+ unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin);
+ NumericLiteralParser Literal(ThisTokBegin, ThisTokBegin+ActualLength,
+ Tok.getLocation(), PP);
+ if (Literal.hadError)
+ return ExprResult(true);
+
+ Expr *Res;
+
+ if (Literal.isFloatingLiteral()) {
+ QualType Ty;
+ const llvm::fltSemantics *Format;
+
+ if (Literal.isFloat) {
+ Ty = Context.FloatTy;
+ Format = Context.Target.getFloatFormat();
+ } else if (!Literal.isLong) {
+ Ty = Context.DoubleTy;
+ Format = Context.Target.getDoubleFormat();
+ } else {
+ Ty = Context.LongDoubleTy;
+ Format = Context.Target.getLongDoubleFormat();
+ }
+
+ // isExact will be set by GetFloatValue().
+ bool isExact = false;
+
+ Res = new FloatingLiteral(Literal.GetFloatValue(*Format,&isExact), &isExact,
+ Ty, Tok.getLocation());
+
+ } else if (!Literal.isIntegerLiteral()) {
+ return ExprResult(true);
+ } else {
+ QualType t;
+
+ // long long is a C99 feature.
+ if (!getLangOptions().C99 && !getLangOptions().CPlusPlus0x &&
+ Literal.isLongLong)
+ Diag(Tok.getLocation(), diag::ext_longlong);
+
+ // Get the value in the widest-possible width.
+ llvm::APInt ResultVal(Context.Target.getIntMaxTWidth(), 0);
+
+ if (Literal.GetIntegerValue(ResultVal)) {
+ // If this value didn't fit into uintmax_t, warn and force to ull.
+ Diag(Tok.getLocation(), diag::warn_integer_too_large);
+ t = Context.UnsignedLongLongTy;
+ assert(Context.getTypeSize(t) == ResultVal.getBitWidth() &&
+ "long long is not intmax_t?");
+ } else {
+ // 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.
+ if (!Literal.isLong && !Literal.isLongLong) {
+ // Are int/unsigned possibilities?
+ unsigned IntSize =
+ static_cast<unsigned>(Context.getTypeSize(Context.IntTy));
+ // Does it fit in a unsigned int?
+ if (ResultVal.isIntN(IntSize)) {
+ // Does it fit in a signed int?
+ if (!Literal.isUnsigned && ResultVal[IntSize-1] == 0)
+ t = Context.IntTy;
+ else if (AllowUnsigned)
+ t = Context.UnsignedIntTy;
+ }
+
+ if (!t.isNull())
+ ResultVal.trunc(IntSize);
+ }
+
+ // Are long/unsigned long possibilities?
+ if (t.isNull() && !Literal.isLongLong) {
+ unsigned LongSize =
+ static_cast<unsigned>(Context.getTypeSize(Context.LongTy));
+
+ // Does it fit in a unsigned long?
+ if (ResultVal.isIntN(LongSize)) {
+ // Does it fit in a signed long?
+ if (!Literal.isUnsigned && ResultVal[LongSize-1] == 0)
+ t = Context.LongTy;
+ else if (AllowUnsigned)
+ t = Context.UnsignedLongTy;
+ }
+ if (!t.isNull())
+ ResultVal.trunc(LongSize);
+ }
+
+ // Finally, check long long if needed.
+ if (t.isNull()) {
+ unsigned LongLongSize =
+ static_cast<unsigned>(Context.getTypeSize(Context.LongLongTy));
+
+ // Does it fit in a unsigned long long?
+ if (ResultVal.isIntN(LongLongSize)) {
+ // Does it fit in a signed long long?
+ if (!Literal.isUnsigned && ResultVal[LongLongSize-1] == 0)
+ t = Context.LongLongTy;
+ else if (AllowUnsigned)
+ t = Context.UnsignedLongLongTy;
+ }
+ }
+
+ // If we still couldn't decide a type, we probably have something that
+ // does not fit in a signed long long, but has no U suffix.
+ if (t.isNull()) {
+ Diag(Tok.getLocation(), diag::warn_integer_too_large_for_signed);
+ t = Context.UnsignedLongLongTy;
+ }
+ }
+
+ Res = new IntegerLiteral(ResultVal, t, Tok.getLocation());
+ }
+
+ // If this is an imaginary literal, create the ImaginaryLiteral wrapper.
+ if (Literal.isImaginary)
+ Res = new ImaginaryLiteral(Res, Context.getComplexType(Res->getType()));
+
+ return Res;
+}
+
+Action::ExprResult Sema::ActOnParenExpr(SourceLocation L, SourceLocation R,
+ ExprTy *Val) {
+ Expr *e = (Expr *)Val;
+ assert((e != 0) && "ActOnParenExpr() missing expr");
+ return new ParenExpr(L, R, e);
+}
+
+/// The UsualUnaryConversions() function is *not* called by this routine.
+/// See C99 6.3.2.1p[2-4] for more details.
+QualType Sema::CheckSizeOfAlignOfOperand(QualType exprType,
+ SourceLocation OpLoc, bool isSizeof) {
+ // C99 6.5.3.4p1:
+ if (isa<FunctionType>(exprType) && isSizeof)
+ // alignof(function) is allowed.
+ Diag(OpLoc, diag::ext_sizeof_function_type);
+ else if (exprType->isVoidType())
+ Diag(OpLoc, diag::ext_sizeof_void_type, isSizeof ? "sizeof" : "__alignof");
+ else if (exprType->isIncompleteType()) {
+ Diag(OpLoc, isSizeof ? diag::err_sizeof_incomplete_type :
+ diag::err_alignof_incomplete_type,
+ exprType.getAsString());
+ return QualType(); // error
+ }
+ // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
+ return Context.getSizeType();
+}
+
+Action::ExprResult Sema::
+ActOnSizeOfAlignOfTypeExpr(SourceLocation OpLoc, bool isSizeof,
+ SourceLocation LPLoc, TypeTy *Ty,
+ SourceLocation RPLoc) {
+ // If error parsing type, ignore.
+ if (Ty == 0) return true;
+
+ // Verify that this is a valid expression.
+ QualType ArgTy = QualType::getFromOpaquePtr(Ty);
+
+ QualType resultType = CheckSizeOfAlignOfOperand(ArgTy, OpLoc, isSizeof);
+
+ if (resultType.isNull())
+ return true;
+ return new SizeOfAlignOfTypeExpr(isSizeof, ArgTy, resultType, OpLoc, RPLoc);
+}
+
+QualType Sema::CheckRealImagOperand(Expr *&V, SourceLocation Loc) {
+ DefaultFunctionArrayConversion(V);
+
+ // These operators return the element type of a complex type.
+ if (const ComplexType *CT = V->getType()->getAsComplexType())
+ return CT->getElementType();
+
+ // Otherwise they pass through real integer and floating point types here.
+ if (V->getType()->isArithmeticType())
+ return V->getType();
+
+ // Reject anything else.
+ Diag(Loc, diag::err_realimag_invalid_type, V->getType().getAsString());
+ return QualType();
+}
+
+
+
+Action::ExprResult Sema::ActOnPostfixUnaryOp(SourceLocation OpLoc,
+ tok::TokenKind Kind,
+ ExprTy *Input) {
+ UnaryOperator::Opcode Opc;
+ switch (Kind) {
+ default: assert(0 && "Unknown unary op!");
+ case tok::plusplus: Opc = UnaryOperator::PostInc; break;
+ case tok::minusminus: Opc = UnaryOperator::PostDec; break;
+ }
+ QualType result = CheckIncrementDecrementOperand((Expr *)Input, OpLoc);
+ if (result.isNull())
+ return true;
+ return new UnaryOperator((Expr *)Input, Opc, result, OpLoc);
+}
+
+Action::ExprResult Sema::
+ActOnArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc,
+ ExprTy *Idx, SourceLocation RLoc) {
+ Expr *LHSExp = static_cast<Expr*>(Base), *RHSExp = static_cast<Expr*>(Idx);
+
+ // Perform default conversions.
+ DefaultFunctionArrayConversion(LHSExp);
+ DefaultFunctionArrayConversion(RHSExp);
+
+ QualType LHSTy = LHSExp->getType(), RHSTy = RHSExp->getType();
+
+ // C99 6.5.2.1p2: the expression e1[e2] is by definition precisely equivalent
+ // to the expression *((e1)+(e2)). This means the array "Base" may actually be
+ // in the subscript position. As a result, we need to derive the array base
+ // and index from the expression types.
+ Expr *BaseExpr, *IndexExpr;
+ QualType ResultType;
+ if (const PointerType *PTy = LHSTy->getAsPointerType()) {
+ BaseExpr = LHSExp;
+ IndexExpr = RHSExp;
+ // FIXME: need to deal with const...
+ ResultType = PTy->getPointeeType();
+ } else if (const PointerType *PTy = RHSTy->getAsPointerType()) {
+ // Handle the uncommon case of "123[Ptr]".
+ BaseExpr = RHSExp;
+ IndexExpr = LHSExp;
+ // FIXME: need to deal with const...
+ ResultType = PTy->getPointeeType();
+ } else if (const VectorType *VTy = LHSTy->getAsVectorType()) {
+ BaseExpr = LHSExp; // vectors: V[123]
+ IndexExpr = RHSExp;
+
+ // Component access limited to variables (reject vec4.rg[1]).
+ if (!isa<DeclRefExpr>(BaseExpr) && !isa<ArraySubscriptExpr>(BaseExpr))
+ return Diag(LLoc, diag::err_ocuvector_component_access,
+ SourceRange(LLoc, RLoc));
+ // FIXME: need to deal with const...
+ ResultType = VTy->getElementType();
+ } else {
+ return Diag(LHSExp->getLocStart(), diag::err_typecheck_subscript_value,
+ RHSExp->getSourceRange());
+ }
+ // C99 6.5.2.1p1
+ if (!IndexExpr->getType()->isIntegerType())
+ return Diag(IndexExpr->getLocStart(), diag::err_typecheck_subscript,
+ IndexExpr->getSourceRange());
+
+ // C99 6.5.2.1p1: "shall have type "pointer to *object* type". In practice,
+ // the following check catches trying to index a pointer to a function (e.g.
+ // void (*)(int)). Functions are not objects in C99.
+ if (!ResultType->isObjectType())
+ return Diag(BaseExpr->getLocStart(),
+ diag::err_typecheck_subscript_not_object,
+ BaseExpr->getType().getAsString(), BaseExpr->getSourceRange());
+
+ return new ArraySubscriptExpr(LHSExp, RHSExp, ResultType, RLoc);
+}
+
+QualType Sema::
+CheckOCUVectorComponent(QualType baseType, SourceLocation OpLoc,
+ IdentifierInfo &CompName, SourceLocation CompLoc) {
+ const OCUVectorType *vecType = baseType->getAsOCUVectorType();
+
+ // The vector accessor can't exceed the number of elements.
+ const char *compStr = CompName.getName();
+ if (strlen(compStr) > vecType->getNumElements()) {
+ Diag(OpLoc, diag::err_ocuvector_component_exceeds_length,
+ baseType.getAsString(), SourceRange(CompLoc));
+ return QualType();
+ }
+ // The component names must come from the same set.
+ if (vecType->getPointAccessorIdx(*compStr) != -1) {
+ do
+ compStr++;
+ while (*compStr && vecType->getPointAccessorIdx(*compStr) != -1);
+ } else if (vecType->getColorAccessorIdx(*compStr) != -1) {
+ do
+ compStr++;
+ while (*compStr && vecType->getColorAccessorIdx(*compStr) != -1);
+ } else if (vecType->getTextureAccessorIdx(*compStr) != -1) {
+ do
+ compStr++;
+ while (*compStr && vecType->getTextureAccessorIdx(*compStr) != -1);
+ }
+
+ if (*compStr) {
+ // We didn't get to the end of the string. This means the component names
+ // didn't come from the same set *or* we encountered an illegal name.
+ Diag(OpLoc, diag::err_ocuvector_component_name_illegal,
+ std::string(compStr,compStr+1), SourceRange(CompLoc));
+ return QualType();
+ }
+ // Each component accessor can't exceed the vector type.
+ compStr = CompName.getName();
+ while (*compStr) {
+ if (vecType->isAccessorWithinNumElements(*compStr))
+ compStr++;
+ else
+ break;
+ }
+ if (*compStr) {
+ // We didn't get to the end of the string. This means a component accessor
+ // exceeds the number of elements in the vector.
+ Diag(OpLoc, diag::err_ocuvector_component_exceeds_length,
+ baseType.getAsString(), SourceRange(CompLoc));
+ return QualType();
+ }
+ // The component accessor looks fine - now we need to compute the actual type.
+ // The vector type is implied by the component accessor. For example,
+ // vec4.b is a float, vec4.xy is a vec2, vec4.rgb is a vec3, etc.
+ unsigned CompSize = strlen(CompName.getName());
+ if (CompSize == 1)
+ return vecType->getElementType();
+
+ QualType VT = Context.getOCUVectorType(vecType->getElementType(), CompSize);
+ // Now look up the TypeDefDecl from the vector type. Without this,
+ // diagostics look bad. We want OCU vector types to appear built-in.
+ for (unsigned i = 0, e = OCUVectorDecls.size(); i != e; ++i) {
+ if (OCUVectorDecls[i]->getUnderlyingType() == VT)
+ return Context.getTypedefType(OCUVectorDecls[i]);
+ }
+ return VT; // should never get here (a typedef type should always be found).
+}
+
+Action::ExprResult Sema::
+ActOnMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
+ tok::TokenKind OpKind, SourceLocation MemberLoc,
+ IdentifierInfo &Member) {
+ Expr *BaseExpr = static_cast<Expr *>(Base);
+ assert(BaseExpr && "no record expression");
+
+ // Perform default conversions.
+ DefaultFunctionArrayConversion(BaseExpr);
+
+ QualType BaseType = BaseExpr->getType();
+ assert(!BaseType.isNull() && "no type for member expression");
+
+ if (OpKind == tok::arrow) {
+ if (const PointerType *PT = BaseType->getAsPointerType())
+ BaseType = PT->getPointeeType();
+ else
+ return Diag(OpLoc, diag::err_typecheck_member_reference_arrow,
+ SourceRange(MemberLoc));
+ }
+ // The base type is either a record or an OCUVectorType.
+ if (const RecordType *RTy = BaseType->getAsRecordType()) {
+ RecordDecl *RDecl = RTy->getDecl();
+ if (RTy->isIncompleteType())
+ return Diag(OpLoc, diag::err_typecheck_incomplete_tag, RDecl->getName(),
+ BaseExpr->getSourceRange());
+ // The record definition is complete, now make sure the member is valid.
+ FieldDecl *MemberDecl = RDecl->getMember(&Member);
+ if (!MemberDecl)
+ return Diag(OpLoc, diag::err_typecheck_no_member, Member.getName(),
+ SourceRange(MemberLoc));
+
+ // Figure out the type of the member; see C99 6.5.2.3p3
+ // FIXME: Handle address space modifiers
+ QualType MemberType = MemberDecl->getType();
+ unsigned combinedQualifiers =
+ MemberType.getCVRQualifiers() | BaseType.getCVRQualifiers();
+ MemberType = MemberType.getQualifiedType(combinedQualifiers);
+
+ return new MemberExpr(BaseExpr, OpKind==tok::arrow, MemberDecl,
+ MemberLoc, MemberType);
+ } else if (BaseType->isOCUVectorType() && OpKind == tok::period) {
+ // Component access limited to variables (reject vec4.rg.g).
+ if (!isa<DeclRefExpr>(BaseExpr))
+ return Diag(OpLoc, diag::err_ocuvector_component_access,
+ SourceRange(MemberLoc));
+ QualType ret = CheckOCUVectorComponent(BaseType, OpLoc, Member, MemberLoc);
+ if (ret.isNull())
+ return true;
+ return new OCUVectorElementExpr(ret, BaseExpr, Member, MemberLoc);
+ } else if (BaseType->isObjCInterfaceType()) {
+ ObjCInterfaceDecl *IFace;
+ if (isa<ObjCInterfaceType>(BaseType.getCanonicalType()))
+ IFace = dyn_cast<ObjCInterfaceType>(BaseType)->getDecl();
+ else
+ IFace = dyn_cast<ObjCQualifiedInterfaceType>(BaseType)->getDecl();
+ ObjCInterfaceDecl *clsDeclared;
+ if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(&Member, clsDeclared))
+ return new ObjCIvarRefExpr(IV, IV->getType(), MemberLoc, BaseExpr,
+ OpKind==tok::arrow);
+ }
+ return Diag(OpLoc, diag::err_typecheck_member_reference_structUnion,
+ SourceRange(MemberLoc));
+}
+
+/// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
+/// This provides the location of the left/right parens and a list of comma
+/// locations.
+Action::ExprResult Sema::
+ActOnCallExpr(ExprTy *fn, SourceLocation LParenLoc,
+ ExprTy **args, unsigned NumArgs,
+ SourceLocation *CommaLocs, SourceLocation RParenLoc) {
+ Expr *Fn = static_cast<Expr *>(fn);
+ Expr **Args = reinterpret_cast<Expr**>(args);
+ assert(Fn && "no function call expression");
+
+ // Make the call expr early, before semantic checks. This guarantees cleanup
+ // of arguments and function on error.
+ llvm::OwningPtr<CallExpr> TheCall(new CallExpr(Fn, Args, NumArgs,
+ Context.BoolTy, RParenLoc));
+
+ // Promote the function operand.
+ TheCall->setCallee(UsualUnaryConversions(Fn));
+
+ // 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)
+ return Diag(Fn->getLocStart(), diag::err_typecheck_call_not_function,
+ SourceRange(Fn->getLocStart(), RParenLoc));
+ const FunctionType *FuncT = PT->getPointeeType()->getAsFunctionType();
+ if (FuncT == 0)
+ return Diag(Fn->getLocStart(), diag::err_typecheck_call_not_function,
+ SourceRange(Fn->getLocStart(), RParenLoc));
+
+ // We know the result type of the call, set it.
+ TheCall->setType(FuncT->getResultType());
+
+ if (const FunctionTypeProto *Proto = dyn_cast<FunctionTypeProto>(FuncT)) {
+ // C99 6.5.2.2p7 - the arguments are implicitly converted, as if by
+ // assignment, to the types of the corresponding parameter, ...
+ unsigned NumArgsInProto = Proto->getNumArgs();
+ unsigned NumArgsToCheck = NumArgs;
+
+ // If too few arguments are available, don't make the call.
+ if (NumArgs < NumArgsInProto)
+ return Diag(RParenLoc, diag::err_typecheck_call_too_few_args,
+ Fn->getSourceRange());
+
+ // If too many are passed and not variadic, error on the extras and drop
+ // them.
+ if (NumArgs > NumArgsInProto) {
+ if (!Proto->isVariadic()) {
+ Diag(Args[NumArgsInProto]->getLocStart(),
+ diag::err_typecheck_call_too_many_args, Fn->getSourceRange(),
+ SourceRange(Args[NumArgsInProto]->getLocStart(),
+ Args[NumArgs-1]->getLocEnd()));
+ // This deletes the extra arguments.
+ TheCall->setNumArgs(NumArgsInProto);
+ }
+ NumArgsToCheck = NumArgsInProto;
+ }
+
+ // Continue to check argument types (even if we have too few/many args).
+ for (unsigned i = 0; i != NumArgsToCheck; i++) {
+ Expr *Arg = Args[i];
+ QualType ProtoArgType = Proto->getArgType(i);
+ QualType ArgType = Arg->getType();
+
+ // Compute implicit casts from the operand to the formal argument type.
+ AssignConvertType ConvTy =
+ CheckSingleAssignmentConstraints(ProtoArgType, Arg);
+ TheCall->setArg(i, Arg);
+
+ if (DiagnoseAssignmentResult(ConvTy, Arg->getLocStart(), ProtoArgType,
+ ArgType, Arg, "passing"))
+ return true;
+ }
+
+ // If this is a variadic call, handle args passed through "...".
+ if (Proto->isVariadic()) {
+ // Promote the arguments (C99 6.5.2.2p7).
+ for (unsigned i = NumArgsInProto; i != NumArgs; i++) {
+ Expr *Arg = Args[i];
+ DefaultArgumentPromotion(Arg);
+ TheCall->setArg(i, Arg);
+ }
+ }
+ } else {
+ assert(isa<FunctionTypeNoProto>(FuncT) && "Unknown FunctionType!");
+
+ // Promote the arguments (C99 6.5.2.2p6).
+ for (unsigned i = 0; i != NumArgs; i++) {
+ Expr *Arg = Args[i];
+ DefaultArgumentPromotion(Arg);
+ TheCall->setArg(i, Arg);
+ }
+ }
+
+ // Do special checking on direct calls to functions.
+ if (ImplicitCastExpr *IcExpr = dyn_cast<ImplicitCastExpr>(Fn))
+ if (DeclRefExpr *DRExpr = dyn_cast<DeclRefExpr>(IcExpr->getSubExpr()))
+ if (FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRExpr->getDecl()))
+ if (CheckFunctionCall(FDecl, TheCall.get()))
+ return true;
+
+ return TheCall.take();
+}
+
+Action::ExprResult Sema::
+ActOnCompoundLiteral(SourceLocation LParenLoc, TypeTy *Ty,
+ SourceLocation RParenLoc, ExprTy *InitExpr) {
+ assert((Ty != 0) && "ActOnCompoundLiteral(): missing type");
+ QualType literalType = QualType::getFromOpaquePtr(Ty);
+ // FIXME: put back this assert when initializers are worked out.
+ //assert((InitExpr != 0) && "ActOnCompoundLiteral(): missing expression");
+ Expr *literalExpr = static_cast<Expr*>(InitExpr);
+
+ // FIXME: add more semantic analysis (C99 6.5.2.5).
+ if (CheckInitializerTypes(literalExpr, literalType))
+ return true;
+
+ bool isFileScope = !CurFunctionDecl && !CurMethodDecl;
+ if (isFileScope) { // 6.5.2.5p3
+ if (CheckForConstantInitializer(literalExpr, literalType))
+ return true;
+ }
+ return new CompoundLiteralExpr(LParenLoc, literalType, literalExpr, isFileScope);
+}
+
+Action::ExprResult Sema::
+ActOnInitList(SourceLocation LBraceLoc, ExprTy **initlist, unsigned NumInit,
+ SourceLocation RBraceLoc) {
+ Expr **InitList = reinterpret_cast<Expr**>(initlist);
+
+ // Semantic analysis for initializers is done by ActOnDeclarator() and
+ // CheckInitializer() - it requires knowledge of the object being intialized.
+
+ InitListExpr *e = new InitListExpr(LBraceLoc, InitList, NumInit, RBraceLoc);
+ e->setType(Context.VoidTy); // FIXME: just a place holder for now.
+ return e;
+}
+
+bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty) {
+ assert(VectorTy->isVectorType() && "Not a vector type!");
+
+ if (Ty->isVectorType() || Ty->isIntegerType()) {
+ if (Context.getTypeSize(VectorTy) != Context.getTypeSize(Ty))
+ return Diag(R.getBegin(),
+ Ty->isVectorType() ?
+ diag::err_invalid_conversion_between_vectors :
+ diag::err_invalid_conversion_between_vector_and_integer,
+ VectorTy.getAsString().c_str(),
+ Ty.getAsString().c_str(), R);
+ } else
+ return Diag(R.getBegin(),
+ diag::err_invalid_conversion_between_vector_and_scalar,
+ VectorTy.getAsString().c_str(),
+ Ty.getAsString().c_str(), R);
+
+ return false;
+}
+
+Action::ExprResult Sema::
+ActOnCastExpr(SourceLocation LParenLoc, TypeTy *Ty,
+ SourceLocation RParenLoc, ExprTy *Op) {
+ assert((Ty != 0) && (Op != 0) && "ActOnCastExpr(): missing type or expr");
+
+ Expr *castExpr = static_cast<Expr*>(Op);
+ QualType castType = QualType::getFromOpaquePtr(Ty);
+
+ 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.
+ if (!castType->isScalarType() && !castType->isVectorType())
+ return Diag(LParenLoc, diag::err_typecheck_cond_expect_scalar,
+ castType.getAsString(), SourceRange(LParenLoc, RParenLoc));
+ if (!castExpr->getType()->isScalarType() &&
+ !castExpr->getType()->isVectorType())
+ return Diag(castExpr->getLocStart(),
+ diag::err_typecheck_expect_scalar_operand,
+ castExpr->getType().getAsString(),castExpr->getSourceRange());
+
+ if (castExpr->getType()->isVectorType()) {
+ if (CheckVectorCast(SourceRange(LParenLoc, RParenLoc),
+ castExpr->getType(), castType))
+ return true;
+ } else if (castType->isVectorType()) {
+ if (CheckVectorCast(SourceRange(LParenLoc, RParenLoc),
+ castType, castExpr->getType()))
+ return true;
+ }
+ }
+ return new CastExpr(castType, castExpr, LParenLoc);
+}
+
+/// Note that lex is not null here, even if this is the gnu "x ?: y" extension.
+/// In that case, lex = cond.
+inline QualType Sema::CheckConditionalOperands( // C99 6.5.15
+ Expr *&cond, Expr *&lex, Expr *&rex, SourceLocation questionLoc) {
+ UsualUnaryConversions(cond);
+ UsualUnaryConversions(lex);
+ UsualUnaryConversions(rex);
+ QualType condT = cond->getType();
+ QualType lexT = lex->getType();
+ QualType rexT = rex->getType();
+
+ // first, check the condition.
+ if (!condT->isScalarType()) { // C99 6.5.15p2
+ Diag(cond->getLocStart(), diag::err_typecheck_cond_expect_scalar,
+ condT.getAsString());
+ return QualType();
+ }
+
+ // Now check the two expressions.
+
+ // 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()) {
+ UsualArithmeticConversions(lex, rex);
+ return lex->getType();
+ }
+
+ // If both operands are the same structure or union type, the result is that
+ // type.
+ if (const RecordType *LHSRT = lexT->getAsRecordType()) { // C99 6.5.15p3
+ if (const RecordType *RHSRT = rexT->getAsRecordType())
+ if (LHSRT->getDecl() == RHSRT->getDecl())
+ // "If both the operands have structure or union type, the result has
+ // that type." This implies that CV qualifiers are dropped.
+ return lexT.getUnqualifiedType();
+ }
+
+ // C99 6.5.15p5: "If both operands have void type, the result has void type."
+ if (lexT->isVoidType() && rexT->isVoidType())
+ return lexT.getUnqualifiedType();
+
+ // C99 6.5.15p6 - "if one operand is a null pointer constant, the result has
+ // the type of the other operand."
+ if (lexT->isPointerType() && rex->isNullPointerConstant(Context)) {
+ ImpCastExprToType(rex, lexT); // promote the null to a pointer.
+ return lexT;
+ }
+ if (rexT->isPointerType() && lex->isNullPointerConstant(Context)) {
+ ImpCastExprToType(lex, rexT); // promote the null to a pointer.
+ return rexT;
+ }
+ // Handle the case where both operands are pointers before we handle null
+ // pointer constants in case both operands are null pointer constants.
+ if (const PointerType *LHSPT = lexT->getAsPointerType()) { // C99 6.5.15p3,6
+ if (const PointerType *RHSPT = rexT->getAsPointerType()) {
+ // get the "pointed to" types
+ QualType lhptee = LHSPT->getPointeeType();
+ QualType rhptee = RHSPT->getPointeeType();
+
+ // ignore qualifiers on void (C99 6.5.15p3, clause 6)
+ if (lhptee->isVoidType() &&
+ (rhptee->isObjectType() || rhptee->isIncompleteType())) {
+ // Figure out necessary qualifiers (C99 6.5.15p6)
+ QualType destPointee=lhptee.getQualifiedType(rhptee.getCVRQualifiers());
+ QualType destType = Context.getPointerType(destPointee);
+ ImpCastExprToType(lex, destType); // add qualifiers if necessary
+ ImpCastExprToType(rex, destType); // promote to void*
+ return destType;
+ }
+ if (rhptee->isVoidType() &&
+ (lhptee->isObjectType() || lhptee->isIncompleteType())) {
+ QualType destPointee=rhptee.getQualifiedType(lhptee.getCVRQualifiers());
+ QualType destType = Context.getPointerType(destPointee);
+ ImpCastExprToType(lex, destType); // add qualifiers if necessary
+ ImpCastExprToType(rex, destType); // promote to void*
+ return destType;
+ }
+
+ if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(),
+ rhptee.getUnqualifiedType())) {
+ Diag(questionLoc, diag::warn_typecheck_cond_incompatible_pointers,
+ lexT.getAsString(), rexT.getAsString(),
+ lex->getSourceRange(), rex->getSourceRange());
+ // 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 voidPtrTy = Context.getPointerType(Context.VoidTy);
+ ImpCastExprToType(lex, voidPtrTy);
+ ImpCastExprToType(rex, voidPtrTy);
+ return voidPtrTy;
+ }
+ // The pointer types are compatible.
+ // 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.
+ // FIXME: Need to return the composite type.
+ // FIXME: Need to add qualifiers
+ return lexT;
+ }
+ }
+
+ // Otherwise, the operands are not compatible.
+ Diag(questionLoc, diag::err_typecheck_cond_incompatible_operands,
+ lexT.getAsString(), rexT.getAsString(),
+ lex->getSourceRange(), rex->getSourceRange());
+ return QualType();
+}
+
+/// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null
+/// in the case of a the GNU conditional expr extension.
+Action::ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
+ SourceLocation ColonLoc,
+ ExprTy *Cond, ExprTy *LHS,
+ ExprTy *RHS) {
+ Expr *CondExpr = (Expr *) Cond;
+ Expr *LHSExpr = (Expr *) LHS, *RHSExpr = (Expr *) RHS;
+
+ // 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;
+
+ QualType result = CheckConditionalOperands(CondExpr, LHSExpr,
+ RHSExpr, QuestionLoc);
+ if (result.isNull())
+ return true;
+ return new ConditionalOperator(CondExpr, isLHSNull ? 0 : LHSExpr,
+ RHSExpr, result);
+}
+
+/// 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 (Ty == Context.FloatTy)
+ ImpCastExprToType(Expr, Context.DoubleTy);
+ else
+ UsualUnaryConversions(Expr);
+}
+
+/// DefaultFunctionArrayConversion (C99 6.3.2.1p3, C99 6.3.2.1p4).
+void Sema::DefaultFunctionArrayConversion(Expr *&e) {
+ QualType t = e->getType();
+ assert(!t.isNull() && "DefaultFunctionArrayConversion - missing type");
+
+ if (const ReferenceType *ref = t->getAsReferenceType()) {
+ ImpCastExprToType(e, ref->getReferenceeType()); // C++ [expr]
+ t = e->getType();
+ }
+ if (t->isFunctionType())
+ ImpCastExprToType(e, Context.getPointerType(t));
+ else if (const ArrayType *ary = t->getAsArrayType()) {
+ // Make sure we don't lose qualifiers when dealing with typedefs. Example:
+ // typedef int arr[10];
+ // void test2() {
+ // const arr b;
+ // b[4] = 1;
+ // }
+ QualType ELT = ary->getElementType();
+ // FIXME: Handle ASQualType
+ ELT = ELT.getQualifiedType(t.getCVRQualifiers()|ELT.getCVRQualifiers());
+ ImpCastExprToType(e, Context.getPointerType(ELT));
+ }
+}
+
+/// UsualUnaryConversions - Performs various conversions that are common to most
+/// operators (C99 6.3). The conversions of array and function types are
+/// sometimes surpressed. For example, the array->pointer conversion doesn't
+/// apply if the array is an argument to the sizeof or address (&) operators.
+/// In these instances, this routine should *not* be called.
+Expr *Sema::UsualUnaryConversions(Expr *&Expr) {
+ QualType Ty = Expr->getType();
+ assert(!Ty.isNull() && "UsualUnaryConversions - missing type");
+
+ if (const ReferenceType *Ref = Ty->getAsReferenceType()) {
+ ImpCastExprToType(Expr, Ref->getReferenceeType()); // C++ [expr]
+ Ty = Expr->getType();
+ }
+ if (Ty->isPromotableIntegerType()) // C99 6.3.1.1p2
+ ImpCastExprToType(Expr, Context.IntTy);
+ else
+ DefaultFunctionArrayConversion(Expr);
+
+ return Expr;
+}
+
+/// UsualArithmeticConversions - Performs various conversions that are common to
+/// binary operators (C99 6.3.1.8). If both operands aren't arithmetic, this
+/// routine returns the first non-arithmetic type found. The client is
+/// responsible for emitting appropriate error diagnostics.
+/// FIXME: verify the conversion rules for "complex int" are consistent with GCC.
+QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
+ bool isCompAssign) {
+ if (!isCompAssign) {
+ UsualUnaryConversions(lhsExpr);
+ UsualUnaryConversions(rhsExpr);
+ }
+ // For conversion purposes, we ignore any qualifiers.
+ // For example, "const float" and "float" are equivalent.
+ QualType lhs = lhsExpr->getType().getCanonicalType().getUnqualifiedType();
+ QualType rhs = rhsExpr->getType().getCanonicalType().getUnqualifiedType();
+
+ // If both types are identical, no conversion is needed.
+ if (lhs == rhs)
+ return lhs;
+
+ // If either side is a non-arithmetic type (e.g. a pointer), we are done.
+ // The caller can deal with this (e.g. pointer + int).
+ if (!lhs->isArithmeticType() || !rhs->isArithmeticType())
+ return lhs;
+
+ // At this point, we have two different arithmetic types.
+
+ // Handle complex types first (C99 6.3.1.8p1).
+ if (lhs->isComplexType() || rhs->isComplexType()) {
+ // if we have an integer operand, the result is the complex type.
+ if (rhs->isIntegerType() || rhs->isComplexIntegerType()) {
+ // convert the rhs to the lhs complex type.
+ if (!isCompAssign) ImpCastExprToType(rhsExpr, lhs);
+ return lhs;
+ }
+ if (lhs->isIntegerType() || lhs->isComplexIntegerType()) {
+ // convert the lhs to the rhs complex type.
+ if (!isCompAssign) ImpCastExprToType(lhsExpr, rhs);
+ return rhs;
+ }
+ // This handles complex/complex, complex/float, or float/complex.
+ // When both operands are complex, the shorter operand is converted to the
+ // type of the longer, and that is the type of the result. This corresponds
+ // to what is done when combining two real floating-point operands.
+ // The fun begins when size promotion occur across type domains.
+ // From H&S 6.3.4: When one operand is complex and the other is a real
+ // floating-point type, the less precise type is converted, within it's
+ // real or complex domain, to the precision of the other type. For example,
+ // when combining a "long double" with a "double _Complex", the
+ // "double _Complex" is promoted to "long double _Complex".
+ int result = Context.compareFloatingType(lhs, rhs);
+
+ if (result > 0) { // The left side is bigger, convert rhs.
+ rhs = Context.getFloatingTypeOfSizeWithinDomain(lhs, rhs);
+ if (!isCompAssign)
+ ImpCastExprToType(rhsExpr, rhs);
+ } else if (result < 0) { // The right side is bigger, convert lhs.
+ lhs = Context.getFloatingTypeOfSizeWithinDomain(rhs, lhs);
+ if (!isCompAssign)
+ ImpCastExprToType(lhsExpr, lhs);
+ }
+ // At this point, lhs and rhs have the same rank/size. Now, make sure the
+ // domains match. This is a requirement for our implementation, C99
+ // does not require this promotion.
+ if (lhs != rhs) { // Domains don't match, we have complex/float mix.
+ if (lhs->isRealFloatingType()) { // handle "double, _Complex double".
+ if (!isCompAssign)
+ ImpCastExprToType(lhsExpr, rhs);
+ return rhs;
+ } else { // handle "_Complex double, double".
+ if (!isCompAssign)
+ ImpCastExprToType(rhsExpr, lhs);
+ return lhs;
+ }
+ }
+ return lhs; // The domain/size match exactly.
+ }
+ // Now handle "real" floating types (i.e. float, double, long double).
+ if (lhs->isRealFloatingType() || rhs->isRealFloatingType()) {
+ // if we have an integer operand, the result is the real floating type.
+ if (rhs->isIntegerType() || rhs->isComplexIntegerType()) {
+ // convert rhs to the lhs floating point type.
+ if (!isCompAssign) ImpCastExprToType(rhsExpr, lhs);
+ return lhs;
+ }
+ if (lhs->isIntegerType() || lhs->isComplexIntegerType()) {
+ // convert lhs to the rhs floating point type.
+ if (!isCompAssign) ImpCastExprToType(lhsExpr, rhs);
+ return rhs;
+ }
+ // We have two real floating types, float/complex combos were handled above.
+ // Convert the smaller operand to the bigger result.
+ int result = Context.compareFloatingType(lhs, rhs);
+
+ if (result > 0) { // convert the rhs
+ if (!isCompAssign) ImpCastExprToType(rhsExpr, lhs);
+ return lhs;
+ }
+ if (result < 0) { // convert the lhs
+ if (!isCompAssign) ImpCastExprToType(lhsExpr, rhs); // convert the lhs
+ return rhs;
+ }
+ assert(0 && "Sema::UsualArithmeticConversions(): illegal float comparison");
+ }
+ if (lhs->isComplexIntegerType() || rhs->isComplexIntegerType()) {
+ // Handle GCC complex int extension.
+ const ComplexType *lhsComplexInt = lhs->getAsComplexIntegerType();
+ const ComplexType *rhsComplexInt = rhs->getAsComplexIntegerType();
+
+ if (lhsComplexInt && rhsComplexInt) {
+ if (Context.maxIntegerType(lhsComplexInt->getElementType(),
+ rhsComplexInt->getElementType()) == lhs) {
+ // convert the rhs
+ if (!isCompAssign) ImpCastExprToType(rhsExpr, lhs);
+ return lhs;
+ }
+ if (!isCompAssign)
+ ImpCastExprToType(lhsExpr, rhs); // convert the lhs
+ return rhs;
+ } else if (lhsComplexInt && rhs->isIntegerType()) {
+ // convert the rhs to the lhs complex type.
+ if (!isCompAssign) ImpCastExprToType(rhsExpr, lhs);
+ return lhs;
+ } else if (rhsComplexInt && lhs->isIntegerType()) {
+ // convert the lhs to the rhs complex type.
+ if (!isCompAssign) ImpCastExprToType(lhsExpr, rhs);
+ return rhs;
+ }
+ }
+ // Finally, we have two differing integer types.
+ if (Context.maxIntegerType(lhs, rhs) == lhs) { // convert the rhs
+ if (!isCompAssign) ImpCastExprToType(rhsExpr, lhs);
+ return lhs;
+ }
+ if (!isCompAssign) ImpCastExprToType(lhsExpr, rhs); // convert the lhs
+ return rhs;
+}
+
+// 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.
+Sema::AssignConvertType
+Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) {
+ QualType lhptee, rhptee;
+
+ // get the "pointed to" type (ignoring qualifiers at the top level)
+ lhptee = lhsType->getAsPointerType()->getPointeeType();
+ rhptee = rhsType->getAsPointerType()->getPointeeType();
+
+ // make sure we operate on the canonical type
+ lhptee = lhptee.getCanonicalType();
+ rhptee = rhptee.getCanonicalType();
+
+ AssignConvertType ConvTy = Compatible;
+
+ // 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;
+ // FIXME: Handle ASQualType
+ if ((lhptee.getCVRQualifiers() & rhptee.getCVRQualifiers()) !=
+ rhptee.getCVRQualifiers())
+ ConvTy = CompatiblePointerDiscardsQualifiers;
+
+ // C99 6.5.16.1p1 (constraint 4): If one operand is a pointer to an object or
+ // incomplete type and the other is a pointer to a qualified or unqualified
+ // version of void...
+ if (lhptee->isVoidType()) {
+ if (rhptee->isObjectType() || rhptee->isIncompleteType())
+ return ConvTy;
+
+ // As an extension, we allow cast to/from void* to function pointer.
+ if (rhptee->isFunctionType())
+ return FunctionVoidPointer;
+ }
+
+ if (rhptee->isVoidType()) {
+ if (lhptee->isObjectType() || lhptee->isIncompleteType())
+ return ConvTy;
+
+ // As an extension, we allow cast to/from void* to function pointer.
+ if (lhptee->isFunctionType())
+ return FunctionVoidPointer;
+ }
+
+ // C99 6.5.16.1p1 (constraint 3): both operands are pointers to qualified or
+ // unqualified versions of compatible types, ...
+ if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(),
+ rhptee.getUnqualifiedType()))
+ return IncompatiblePointer; // this "trumps" PointerAssignDiscardsQualifiers
+ return ConvTy;
+}
+
+/// CheckAssignmentConstraints (C99 6.5.16) - This routine currently
+/// has code to accommodate several GCC extensions when type checking
+/// pointers. Here are some objectionable examples that GCC considers warnings:
+///
+/// int a, *pint;
+/// short *pshort;
+/// struct foo *pfoo;
+///
+/// pint = pshort; // warning: assignment from incompatible pointer type
+/// a = pint; // warning: assignment makes integer from pointer without a cast
+/// pint = a; // warning: assignment makes pointer from integer without a cast
+/// pint = pfoo; // warning: assignment from incompatible pointer type
+///
+/// As a result, the code for dealing with pointers is more complex than the
+/// C99 spec dictates.
+/// Note: the warning above turn into errors when -pedantic-errors is enabled.
+///
+Sema::AssignConvertType
+Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
+ // Get canonical types. We're not formatting these types, just comparing
+ // them.
+ lhsType = lhsType.getCanonicalType();
+ rhsType = rhsType.getCanonicalType();
+
+ if (lhsType.getUnqualifiedType() == rhsType.getUnqualifiedType())
+ return Compatible; // Common case: fast path an exact match.
+
+ if (lhsType->isReferenceType() || rhsType->isReferenceType()) {
+ if (Context.referenceTypesAreCompatible(lhsType, rhsType))
+ return Compatible;
+ return Incompatible;
+ }
+
+ if (lhsType->isObjCQualifiedIdType()
+ || rhsType->isObjCQualifiedIdType()) {
+ if (Context.ObjCQualifiedIdTypesAreCompatible(lhsType, rhsType))
+ return Compatible;
+ return Incompatible;
+ }
+
+ if (lhsType->isVectorType() || rhsType->isVectorType()) {
+ // For OCUVector, allow vector splats; float -> <n x float>
+ if (const OCUVectorType *LV = lhsType->getAsOCUVectorType()) {
+ if (LV->getElementType().getTypePtr() == rhsType.getTypePtr())
+ return Compatible;
+ }
+
+ // If LHS and RHS are both vectors of integer or both vectors of floating
+ // point types, and the total vector length is the same, allow the
+ // conversion. This is a bitcast; no bits are changed but the result type
+ // is different.
+ if (getLangOptions().LaxVectorConversions &&
+ lhsType->isVectorType() && rhsType->isVectorType()) {
+ if ((lhsType->isIntegerType() && rhsType->isIntegerType()) ||
+ (lhsType->isRealFloatingType() && rhsType->isRealFloatingType())) {
+ if (Context.getTypeSize(lhsType) == Context.getTypeSize(rhsType))
+ return Compatible;
+ }
+ }
+ return Incompatible;
+ }
+
+ if (lhsType->isArithmeticType() && rhsType->isArithmeticType())
+ return Compatible;
+
+ if (lhsType->isPointerType()) {
+ if (rhsType->isIntegerType())
+ return IntToPointer;
+
+ if (rhsType->isPointerType())
+ return CheckPointerTypesForAssignment(lhsType, rhsType);
+ return Incompatible;
+ }
+
+ if (rhsType->isPointerType()) {
+ // C99 6.5.16.1p1: the left operand is _Bool and the right is a pointer.
+ if ((lhsType->isIntegerType()) && (lhsType != Context.BoolTy))
+ return PointerToInt;
+
+ if (lhsType->isPointerType())
+ return CheckPointerTypesForAssignment(lhsType, rhsType);
+ return Incompatible;
+ }
+
+ if (isa<TagType>(lhsType) && isa<TagType>(rhsType)) {
+ if (Context.tagTypesAreCompatible(lhsType, rhsType))
+ return Compatible;
+ }
+ return Incompatible;
+}
+
+Sema::AssignConvertType
+Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {
+ // C99 6.5.16.1p1: the left operand is a pointer and the right is
+ // a null pointer constant.
+ if ((lhsType->isPointerType() || lhsType->isObjCQualifiedIdType())
+ && rExpr->isNullPointerConstant(Context)) {
+ ImpCastExprToType(rExpr, lhsType);
+ return Compatible;
+ }
+ // This check seems unnatural, however it is necessary to ensure the proper
+ // conversion of functions/arrays. If the conversion were done for all
+ // DeclExpr's (created by ActOnIdentifierExpr), it would mess up the unary
+ // expressions that surpress this implicit conversion (&, sizeof).
+ //
+ // Suppress this for references: C99 8.5.3p5. FIXME: revisit when references
+ // are better understood.
+ if (!lhsType->isReferenceType())
+ DefaultFunctionArrayConversion(rExpr);
+
+ Sema::AssignConvertType result =
+ CheckAssignmentConstraints(lhsType, rExpr->getType());
+
+ // C99 6.5.16.1p2: The value of the right operand is converted to the
+ // type of the assignment expression.
+ if (rExpr->getType() != lhsType)
+ ImpCastExprToType(rExpr, lhsType);
+ return result;
+}
+
+Sema::AssignConvertType
+Sema::CheckCompoundAssignmentConstraints(QualType lhsType, QualType rhsType) {
+ return CheckAssignmentConstraints(lhsType, rhsType);
+}
+
+QualType Sema::InvalidOperands(SourceLocation loc, Expr *&lex, Expr *&rex) {
+ Diag(loc, diag::err_typecheck_invalid_operands,
+ lex->getType().getAsString(), rex->getType().getAsString(),
+ lex->getSourceRange(), rex->getSourceRange());
+ return QualType();
+}
+
+inline QualType Sema::CheckVectorOperands(SourceLocation loc, Expr *&lex,
+ Expr *&rex) {
+ QualType lhsType = lex->getType(), rhsType = rex->getType();
+
+ // make sure the vector types are identical.
+ if (lhsType == rhsType)
+ return lhsType;
+
+ // if the lhs is an ocu vector and the rhs is a scalar of the same type,
+ // promote the rhs to the vector type.
+ if (const OCUVectorType *V = lhsType->getAsOCUVectorType()) {
+ if (V->getElementType().getCanonicalType().getTypePtr()
+ == rhsType.getCanonicalType().getTypePtr()) {
+ ImpCastExprToType(rex, lhsType);
+ return lhsType;
+ }
+ }
+
+ // if the rhs is an ocu vector and the lhs is a scalar of the same type,
+ // promote the lhs to the vector type.
+ if (const OCUVectorType *V = rhsType->getAsOCUVectorType()) {
+ if (V->getElementType().getCanonicalType().getTypePtr()
+ == lhsType.getCanonicalType().getTypePtr()) {
+ ImpCastExprToType(lex, rhsType);
+ return rhsType;
+ }
+ }
+
+ // You cannot convert between vector values of different size.
+ Diag(loc, diag::err_typecheck_vector_not_convertable,
+ lex->getType().getAsString(), rex->getType().getAsString(),
+ lex->getSourceRange(), rex->getSourceRange());
+ return QualType();
+}
+
+inline QualType Sema::CheckMultiplyDivideOperands(
+ Expr *&lex, Expr *&rex, SourceLocation loc, bool isCompAssign)
+{
+ QualType lhsType = lex->getType(), rhsType = rex->getType();
+
+ if (lhsType->isVectorType() || rhsType->isVectorType())
+ return CheckVectorOperands(loc, lex, rex);
+
+ QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
+
+ if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
+ return compType;
+ return InvalidOperands(loc, lex, rex);
+}
+
+inline QualType Sema::CheckRemainderOperands(
+ Expr *&lex, Expr *&rex, SourceLocation loc, bool isCompAssign)
+{
+ QualType lhsType = lex->getType(), rhsType = rex->getType();
+
+ QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
+
+ if (lex->getType()->isIntegerType() && rex->getType()->isIntegerType())
+ return compType;
+ return InvalidOperands(loc, lex, rex);
+}
+
+inline QualType Sema::CheckAdditionOperands( // C99 6.5.6
+ Expr *&lex, Expr *&rex, SourceLocation loc, bool isCompAssign)
+{
+ if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
+ return CheckVectorOperands(loc, lex, rex);
+
+ QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
+
+ // handle the common case first (both operands are arithmetic).
+ if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
+ return compType;
+
+ if (lex->getType()->isPointerType() && rex->getType()->isIntegerType())
+ return lex->getType();
+ if (lex->getType()->isIntegerType() && rex->getType()->isPointerType())
+ return rex->getType();
+ return InvalidOperands(loc, lex, rex);
+}
+
+inline QualType Sema::CheckSubtractionOperands( // C99 6.5.6
+ Expr *&lex, Expr *&rex, SourceLocation loc, bool isCompAssign)
+{
+ if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
+ return CheckVectorOperands(loc, lex, rex);
+
+ QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
+
+ // Enforce type constraints: C99 6.5.6p3.
+
+ // Handle the common case first (both operands are arithmetic).
+ if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
+ return compType;
+
+ // Either ptr - int or ptr - ptr.
+ if (const PointerType *LHSPTy = lex->getType()->getAsPointerType()) {
+ QualType lpointee = LHSPTy->getPointeeType();
+
+ // The LHS must be an object type, not incomplete, function, etc.
+ if (!lpointee->isObjectType()) {
+ // Handle the GNU void* extension.
+ if (lpointee->isVoidType()) {
+ Diag(loc, diag::ext_gnu_void_ptr,
+ lex->getSourceRange(), rex->getSourceRange());
+ } else {
+ Diag(loc, diag::err_typecheck_sub_ptr_object,
+ lex->getType().getAsString(), lex->getSourceRange());
+ return QualType();
+ }
+ }
+
+ // The result type of a pointer-int computation is the pointer type.
+ if (rex->getType()->isIntegerType())
+ return lex->getType();
+
+ // Handle pointer-pointer subtractions.
+ if (const PointerType *RHSPTy = rex->getType()->getAsPointerType()) {
+ QualType rpointee = RHSPTy->getPointeeType();
+
+ // RHS must be an object type, unless void (GNU).
+ if (!rpointee->isObjectType()) {
+ // Handle the GNU void* extension.
+ if (rpointee->isVoidType()) {
+ if (!lpointee->isVoidType())
+ Diag(loc, diag::ext_gnu_void_ptr,
+ lex->getSourceRange(), rex->getSourceRange());
+ } else {
+ Diag(loc, diag::err_typecheck_sub_ptr_object,
+ rex->getType().getAsString(), rex->getSourceRange());
+ return QualType();
+ }
+ }
+
+ // Pointee types must be compatible.
+ if (!Context.typesAreCompatible(lpointee.getUnqualifiedType(),
+ rpointee.getUnqualifiedType())) {
+ Diag(loc, diag::err_typecheck_sub_ptr_compatible,
+ lex->getType().getAsString(), rex->getType().getAsString(),
+ lex->getSourceRange(), rex->getSourceRange());
+ return QualType();
+ }
+
+ return Context.getPointerDiffType();
+ }
+ }
+
+ return InvalidOperands(loc, lex, rex);
+}
+
+inline QualType Sema::CheckShiftOperands( // C99 6.5.7
+ Expr *&lex, Expr *&rex, SourceLocation loc, bool isCompAssign) {
+ // C99 6.5.7p2: Each of the operands shall have integer type.
+ if (!lex->getType()->isIntegerType() || !rex->getType()->isIntegerType())
+ return InvalidOperands(loc, lex, rex);
+
+ // Shifts don't perform usual arithmetic conversions, they just do integer
+ // promotions on each operand. C99 6.5.7p3
+ if (!isCompAssign)
+ UsualUnaryConversions(lex);
+ UsualUnaryConversions(rex);
+
+ // "The type of the result is that of the promoted left operand."
+ return lex->getType();
+}
+
+inline QualType Sema::CheckCompareOperands( // C99 6.5.8
+ Expr *&lex, Expr *&rex, SourceLocation loc, bool isRelational)
+{
+ // C99 6.5.8p3 / C99 6.5.9p4
+ if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
+ UsualArithmeticConversions(lex, rex);
+ else {
+ UsualUnaryConversions(lex);
+ UsualUnaryConversions(rex);
+ }
+ 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())
+ Diag(loc, diag::warn_selfcomparison);
+ }
+
+ if (isRelational) {
+ if (lType->isRealType() && rType->isRealType())
+ return Context.IntTy;
+ } else {
+ // Check for comparisons of floating point operands using != and ==.
+ if (lType->isFloatingType()) {
+ assert (rType->isFloatingType());
+ CheckFloatComparison(loc,lex,rex);
+ }
+
+ if (lType->isArithmeticType() && rType->isArithmeticType())
+ return Context.IntTy;
+ }
+
+ bool LHSIsNull = lex->isNullPointerConstant(Context);
+ bool RHSIsNull = rex->isNullPointerConstant(Context);
+
+ // 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).
+ if (lType->isPointerType() && rType->isPointerType()) { // C99 6.5.8p2
+ QualType lpointee = lType->getAsPointerType()->getPointeeType();
+ QualType rpointee = rType->getAsPointerType()->getPointeeType();
+
+ if (!LHSIsNull && !RHSIsNull && // C99 6.5.9p2
+ !lpointee->isVoidType() && !lpointee->isVoidType() &&
+ !Context.typesAreCompatible(lpointee.getUnqualifiedType(),
+ rpointee.getUnqualifiedType())) {
+ Diag(loc, diag::ext_typecheck_comparison_of_distinct_pointers,
+ lType.getAsString(), rType.getAsString(),
+ lex->getSourceRange(), rex->getSourceRange());
+ }
+ ImpCastExprToType(rex, lType); // promote the pointer to pointer
+ return Context.IntTy;
+ }
+ if ((lType->isObjCQualifiedIdType() || rType->isObjCQualifiedIdType())
+ && Context.ObjCQualifiedIdTypesAreCompatible(lType, rType, true)) {
+ ImpCastExprToType(rex, lType);
+ return Context.IntTy;
+ }
+ if (lType->isPointerType() && rType->isIntegerType()) {
+ if (!RHSIsNull)
+ Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer,
+ lType.getAsString(), rType.getAsString(),
+ lex->getSourceRange(), rex->getSourceRange());
+ ImpCastExprToType(rex, lType); // promote the integer to pointer
+ return Context.IntTy;
+ }
+ if (lType->isIntegerType() && rType->isPointerType()) {
+ if (!LHSIsNull)
+ Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer,
+ lType.getAsString(), rType.getAsString(),
+ lex->getSourceRange(), rex->getSourceRange());
+ ImpCastExprToType(lex, rType); // promote the integer to pointer
+ return Context.IntTy;
+ }
+ return InvalidOperands(loc, lex, rex);
+}
+
+inline QualType Sema::CheckBitwiseOperands(
+ Expr *&lex, Expr *&rex, SourceLocation loc, bool isCompAssign)
+{
+ if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
+ return CheckVectorOperands(loc, lex, rex);
+
+ QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
+
+ if (lex->getType()->isIntegerType() && rex->getType()->isIntegerType())
+ return compType;
+ return InvalidOperands(loc, lex, rex);
+}
+
+inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]
+ Expr *&lex, Expr *&rex, SourceLocation loc)
+{
+ UsualUnaryConversions(lex);
+ UsualUnaryConversions(rex);
+
+ if (lex->getType()->isScalarType() || rex->getType()->isScalarType())
+ return Context.IntTy;
+ return InvalidOperands(loc, lex, rex);
+}
+
+inline QualType Sema::CheckAssignmentOperands( // C99 6.5.16.1
+ Expr *lex, Expr *&rex, SourceLocation loc, QualType compoundType)
+{
+ QualType lhsType = lex->getType();
+ QualType rhsType = compoundType.isNull() ? rex->getType() : compoundType;
+ Expr::isModifiableLvalueResult mlval = lex->isModifiableLvalue();
+
+ switch (mlval) { // C99 6.5.16p2
+ case Expr::MLV_Valid:
+ break;
+ case Expr::MLV_ConstQualified:
+ Diag(loc, diag::err_typecheck_assign_const, lex->getSourceRange());
+ return QualType();
+ case Expr::MLV_ArrayType:
+ Diag(loc, diag::err_typecheck_array_not_modifiable_lvalue,
+ lhsType.getAsString(), lex->getSourceRange());
+ return QualType();
+ case Expr::MLV_NotObjectType:
+ Diag(loc, diag::err_typecheck_non_object_not_modifiable_lvalue,
+ lhsType.getAsString(), lex->getSourceRange());
+ return QualType();
+ case Expr::MLV_InvalidExpression:
+ Diag(loc, diag::err_typecheck_expression_not_modifiable_lvalue,
+ lex->getSourceRange());
+ return QualType();
+ case Expr::MLV_IncompleteType:
+ case Expr::MLV_IncompleteVoidType:
+ Diag(loc, diag::err_typecheck_incomplete_type_not_modifiable_lvalue,
+ lhsType.getAsString(), lex->getSourceRange());
+ return QualType();
+ case Expr::MLV_DuplicateVectorComponents:
+ Diag(loc, diag::err_typecheck_duplicate_vector_components_not_mlvalue,
+ lex->getSourceRange());
+ return QualType();
+ }
+
+ AssignConvertType ConvTy;
+ if (compoundType.isNull())
+ ConvTy = CheckSingleAssignmentConstraints(lhsType, rex);
+ else
+ ConvTy = CheckCompoundAssignmentConstraints(lhsType, rhsType);
+
+ if (DiagnoseAssignmentResult(ConvTy, loc, lhsType, rhsType,
+ rex, "assigning"))
+ return QualType();
+
+ // 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).
+ // C++ 5.17p1: the type of the assignment expression is that of its left
+ // oprdu.
+ return lhsType.getUnqualifiedType();
+}
+
+inline QualType Sema::CheckCommaOperands( // C99 6.5.17
+ Expr *&lex, Expr *&rex, SourceLocation loc) {
+ UsualUnaryConversions(rex);
+ return rex->getType();
+}
+
+/// CheckIncrementDecrementOperand - unlike most "Check" methods, this routine
+/// doesn't need to call UsualUnaryConversions or UsualArithmeticConversions.
+QualType Sema::CheckIncrementDecrementOperand(Expr *op, SourceLocation OpLoc) {
+ QualType resType = op->getType();
+ assert(!resType.isNull() && "no type for increment/decrement expression");
+
+ // C99 6.5.2.4p1: We allow complex as a GCC extension.
+ if (const PointerType *pt = resType->getAsPointerType()) {
+ if (!pt->getPointeeType()->isObjectType()) { // C99 6.5.2.4p2, 6.5.6p2
+ Diag(OpLoc, diag::err_typecheck_arithmetic_incomplete_type,
+ resType.getAsString(), op->getSourceRange());
+ return QualType();
+ }
+ } else if (!resType->isRealType()) {
+ if (resType->isComplexType())
+ // C99 does not support ++/-- on complex types.
+ Diag(OpLoc, diag::ext_integer_increment_complex,
+ resType.getAsString(), op->getSourceRange());
+ else {
+ Diag(OpLoc, diag::err_typecheck_illegal_increment_decrement,
+ resType.getAsString(), op->getSourceRange());
+ return QualType();
+ }
+ }
+ // At this point, we know we have a real, complex or pointer type.
+ // Now make sure the operand is a modifiable lvalue.
+ Expr::isModifiableLvalueResult mlval = op->isModifiableLvalue();
+ if (mlval != Expr::MLV_Valid) {
+ // FIXME: emit a more precise diagnostic...
+ Diag(OpLoc, diag::err_typecheck_invalid_lvalue_incr_decr,
+ op->getSourceRange());
+ return QualType();
+ }
+ return resType;
+}
+
+/// getPrimaryDecl - Helper function for CheckAddressOfOperand().
+/// This routine allows us to typecheck complex/recursive expressions
+/// where the declaration is needed for type checking. Here are some
+/// examples: &s.xx, &s.zz[1].yy, &(1+2), &(XX), &"123"[2].
+static ValueDecl *getPrimaryDecl(Expr *e) {
+ switch (e->getStmtClass()) {
+ case Stmt::DeclRefExprClass:
+ return cast<DeclRefExpr>(e)->getDecl();
+ case Stmt::MemberExprClass:
+ // Fields cannot be declared with a 'register' storage class.
+ // &X->f is always ok, even if X is declared register.
+ if (cast<MemberExpr>(e)->isArrow())
+ return 0;
+ return getPrimaryDecl(cast<MemberExpr>(e)->getBase());
+ case Stmt::ArraySubscriptExprClass: {
+ // &X[4] and &4[X] is invalid if X is invalid and X is not a pointer.
+
+ ValueDecl *VD = getPrimaryDecl(cast<ArraySubscriptExpr>(e)->getBase());
+ if (!VD || VD->getType()->isPointerType())
+ return 0;
+ else
+ return VD;
+ }
+ case Stmt::UnaryOperatorClass:
+ return getPrimaryDecl(cast<UnaryOperator>(e)->getSubExpr());
+ case Stmt::ParenExprClass:
+ return getPrimaryDecl(cast<ParenExpr>(e)->getSubExpr());
+ case Stmt::ImplicitCastExprClass:
+ // &X[4] when X is an array, has an implicit cast from array to pointer.
+ return getPrimaryDecl(cast<ImplicitCastExpr>(e)->getSubExpr());
+ default:
+ return 0;
+ }
+}
+
+/// CheckAddressOfOperand - The operand of & must be either a function
+/// designator or an lvalue designating an object. If it is an lvalue, the
+/// object cannot be declared with storage class register or be a bit field.
+/// Note: The usual conversions are *not* applied to the operand of the &
+/// operator (C99 6.3.2.1p[2-4]), and its result is never an lvalue.
+QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) {
+ 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.
+ }
+ ValueDecl *dcl = getPrimaryDecl(op);
+ Expr::isLvalueResult lval = op->isLvalue();
+
+ if (lval != Expr::LV_Valid) { // C99 6.5.3.2p1
+ if (!dcl || !isa<FunctionDecl>(dcl)) {// allow function designators
+ // FIXME: emit more specific diag...
+ Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof,
+ op->getSourceRange());
+ return QualType();
+ }
+ } else if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(op)) { // C99 6.5.3.2p1
+ if (MemExpr->getMemberDecl()->isBitField()) {
+ Diag(OpLoc, diag::err_typecheck_address_of,
+ std::string("bit-field"), op->getSourceRange());
+ return QualType();
+ }
+ // Check for Apple extension for accessing vector components.
+ } else if (isa<ArraySubscriptExpr>(op) &&
+ cast<ArraySubscriptExpr>(op)->getBase()->getType()->isVectorType()) {
+ Diag(OpLoc, diag::err_typecheck_address_of,
+ std::string("vector"), op->getSourceRange());
+ return QualType();
+ } else if (dcl) { // C99 6.5.3.2p1
+ // We have an lvalue with a decl. Make sure the decl is not declared
+ // with the register storage-class specifier.
+ if (const VarDecl *vd = dyn_cast<VarDecl>(dcl)) {
+ if (vd->getStorageClass() == VarDecl::Register) {
+ Diag(OpLoc, diag::err_typecheck_address_of,
+ std::string("register variable"), op->getSourceRange());
+ return QualType();
+ }
+ } else
+ assert(0 && "Unknown/unexpected decl type");
+ }
+ // If the operand has type "type", the result has type "pointer to type".
+ return Context.getPointerType(op->getType());
+}
+
+QualType Sema::CheckIndirectionOperand(Expr *op, SourceLocation OpLoc) {
+ UsualUnaryConversions(op);
+ QualType qType = op->getType();
+
+ if (const PointerType *PT = qType->getAsPointerType()) {
+ // 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.
+ return PT->getPointeeType();
+ }
+ Diag(OpLoc, diag::err_typecheck_indirection_requires_pointer,
+ qType.getAsString(), op->getSourceRange());
+ return QualType();
+}
+
+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;
+}
+
+static inline UnaryOperator::Opcode ConvertTokenKindToUnaryOpcode(
+ tok::TokenKind Kind) {
+ UnaryOperator::Opcode Opc;
+ switch (Kind) {
+ default: assert(0 && "Unknown unary op!");
+ case tok::plusplus: Opc = UnaryOperator::PreInc; break;
+ case tok::minusminus: Opc = UnaryOperator::PreDec; break;
+ case tok::amp: Opc = UnaryOperator::AddrOf; break;
+ case tok::star: Opc = UnaryOperator::Deref; break;
+ case tok::plus: Opc = UnaryOperator::Plus; break;
+ case tok::minus: Opc = UnaryOperator::Minus; break;
+ case tok::tilde: Opc = UnaryOperator::Not; break;
+ case tok::exclaim: Opc = UnaryOperator::LNot; break;
+ case tok::kw_sizeof: Opc = UnaryOperator::SizeOf; break;
+ case tok::kw___alignof: Opc = UnaryOperator::AlignOf; break;
+ case tok::kw___real: Opc = UnaryOperator::Real; break;
+ case tok::kw___imag: Opc = UnaryOperator::Imag; break;
+ case tok::kw___extension__: Opc = UnaryOperator::Extension; break;
+ }
+ return Opc;
+}
+
+// Binary Operators. 'Tok' is the token for the operator.
+Action::ExprResult Sema::ActOnBinOp(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");
+
+ QualType ResultTy; // Result type of the binary operator.
+ QualType CompTy; // Computation type for compound assignments (e.g. '+=')
+
+ switch (Opc) {
+ default:
+ assert(0 && "Unknown binary expr!");
+ case BinaryOperator::Assign:
+ ResultTy = CheckAssignmentOperands(lhs, rhs, TokLoc, QualType());
+ break;
+ case BinaryOperator::Mul:
+ case BinaryOperator::Div:
+ ResultTy = CheckMultiplyDivideOperands(lhs, rhs, TokLoc);
+ break;
+ case BinaryOperator::Rem:
+ ResultTy = CheckRemainderOperands(lhs, rhs, TokLoc);
+ break;
+ case BinaryOperator::Add:
+ ResultTy = CheckAdditionOperands(lhs, rhs, TokLoc);
+ break;
+ case BinaryOperator::Sub:
+ ResultTy = CheckSubtractionOperands(lhs, rhs, TokLoc);
+ break;
+ case BinaryOperator::Shl:
+ case BinaryOperator::Shr:
+ ResultTy = CheckShiftOperands(lhs, rhs, TokLoc);
+ break;
+ case BinaryOperator::LE:
+ case BinaryOperator::LT:
+ case BinaryOperator::GE:
+ case BinaryOperator::GT:
+ ResultTy = CheckCompareOperands(lhs, rhs, TokLoc, true);
+ break;
+ case BinaryOperator::EQ:
+ case BinaryOperator::NE:
+ ResultTy = CheckCompareOperands(lhs, rhs, TokLoc, false);
+ break;
+ case BinaryOperator::And:
+ case BinaryOperator::Xor:
+ case BinaryOperator::Or:
+ ResultTy = CheckBitwiseOperands(lhs, rhs, TokLoc);
+ break;
+ case BinaryOperator::LAnd:
+ case BinaryOperator::LOr:
+ ResultTy = CheckLogicalOperands(lhs, rhs, TokLoc);
+ break;
+ case BinaryOperator::MulAssign:
+ case BinaryOperator::DivAssign:
+ CompTy = CheckMultiplyDivideOperands(lhs, rhs, TokLoc, true);
+ if (!CompTy.isNull())
+ ResultTy = CheckAssignmentOperands(lhs, rhs, TokLoc, CompTy);
+ break;
+ case BinaryOperator::RemAssign:
+ CompTy = CheckRemainderOperands(lhs, rhs, TokLoc, true);
+ if (!CompTy.isNull())
+ ResultTy = CheckAssignmentOperands(lhs, rhs, TokLoc, CompTy);
+ break;
+ case BinaryOperator::AddAssign:
+ CompTy = CheckAdditionOperands(lhs, rhs, TokLoc, true);
+ if (!CompTy.isNull())
+ ResultTy = CheckAssignmentOperands(lhs, rhs, TokLoc, CompTy);
+ break;
+ case BinaryOperator::SubAssign:
+ CompTy = CheckSubtractionOperands(lhs, rhs, TokLoc, true);
+ if (!CompTy.isNull())
+ ResultTy = CheckAssignmentOperands(lhs, rhs, TokLoc, CompTy);
+ break;
+ case BinaryOperator::ShlAssign:
+ case BinaryOperator::ShrAssign:
+ CompTy = CheckShiftOperands(lhs, rhs, TokLoc, true);
+ if (!CompTy.isNull())
+ ResultTy = CheckAssignmentOperands(lhs, rhs, TokLoc, CompTy);
+ break;
+ case BinaryOperator::AndAssign:
+ case BinaryOperator::XorAssign:
+ case BinaryOperator::OrAssign:
+ CompTy = CheckBitwiseOperands(lhs, rhs, TokLoc, true);
+ if (!CompTy.isNull())
+ ResultTy = CheckAssignmentOperands(lhs, rhs, TokLoc, CompTy);
+ break;
+ case BinaryOperator::Comma:
+ ResultTy = CheckCommaOperands(lhs, rhs, TokLoc);
+ break;
+ }
+ if (ResultTy.isNull())
+ return true;
+ if (CompTy.isNull())
+ return new BinaryOperator(lhs, rhs, Opc, ResultTy, TokLoc);
+ else
+ return new CompoundAssignOperator(lhs, rhs, Opc, ResultTy, CompTy, TokLoc);
+}
+
+// Unary Operators. 'Tok' is the token for the operator.
+Action::ExprResult Sema::ActOnUnaryOp(SourceLocation OpLoc, tok::TokenKind Op,
+ ExprTy *input) {
+ Expr *Input = (Expr*)input;
+ UnaryOperator::Opcode Opc = ConvertTokenKindToUnaryOpcode(Op);
+ QualType resultType;
+ switch (Opc) {
+ default:
+ assert(0 && "Unimplemented unary expr!");
+ case UnaryOperator::PreInc:
+ case UnaryOperator::PreDec:
+ resultType = CheckIncrementDecrementOperand(Input, OpLoc);
+ break;
+ case UnaryOperator::AddrOf:
+ resultType = CheckAddressOfOperand(Input, OpLoc);
+ break;
+ case UnaryOperator::Deref:
+ DefaultFunctionArrayConversion(Input);
+ resultType = CheckIndirectionOperand(Input, OpLoc);
+ break;
+ case UnaryOperator::Plus:
+ case UnaryOperator::Minus:
+ UsualUnaryConversions(Input);
+ resultType = Input->getType();
+ if (!resultType->isArithmeticType()) // C99 6.5.3.3p1
+ return Diag(OpLoc, diag::err_typecheck_unary_expr,
+ resultType.getAsString());
+ break;
+ case UnaryOperator::Not: // bitwise complement
+ UsualUnaryConversions(Input);
+ resultType = Input->getType();
+ // C99 6.5.3.3p1. We allow complex as a GCC extension.
+ if (!resultType->isIntegerType()) {
+ if (resultType->isComplexType())
+ // C99 does not support '~' for complex conjugation.
+ Diag(OpLoc, diag::ext_integer_complement_complex,
+ resultType.getAsString());
+ else
+ return Diag(OpLoc, diag::err_typecheck_unary_expr,
+ resultType.getAsString());
+ }
+ break;
+ case UnaryOperator::LNot: // logical negation
+ // Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5).
+ DefaultFunctionArrayConversion(Input);
+ resultType = Input->getType();
+ if (!resultType->isScalarType()) // C99 6.5.3.3p1
+ return Diag(OpLoc, diag::err_typecheck_unary_expr,
+ resultType.getAsString());
+ // LNot always has type int. C99 6.5.3.3p5.
+ resultType = Context.IntTy;
+ break;
+ case UnaryOperator::SizeOf:
+ resultType = CheckSizeOfAlignOfOperand(Input->getType(), OpLoc, true);
+ break;
+ case UnaryOperator::AlignOf:
+ resultType = CheckSizeOfAlignOfOperand(Input->getType(), OpLoc, false);
+ break;
+ case UnaryOperator::Real:
+ case UnaryOperator::Imag:
+ resultType = CheckRealImagOperand(Input, OpLoc);
+ break;
+ case UnaryOperator::Extension:
+ resultType = Input->getType();
+ break;
+ }
+ if (resultType.isNull())
+ return true;
+ return new UnaryOperator(Input, Opc, resultType, OpLoc);
+}
+
+/// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo".
+Sema::ExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc,
+ SourceLocation LabLoc,
+ IdentifierInfo *LabelII) {
+ // Look up the record for this label identifier.
+ LabelStmt *&LabelDecl = LabelMap[LabelII];
+
+ // If we haven't seen this label yet, create a forward reference.
+ if (LabelDecl == 0)
+ LabelDecl = new LabelStmt(LabLoc, LabelII, 0);
+
+ // Create the AST node. The address of a label always has type 'void*'.
+ return new AddrLabelExpr(OpLoc, LabLoc, LabelDecl,
+ Context.getPointerType(Context.VoidTy));
+}
+
+Sema::ExprResult Sema::ActOnStmtExpr(SourceLocation LPLoc, StmtTy *substmt,
+ SourceLocation RPLoc) { // "({..})"
+ Stmt *SubStmt = static_cast<Stmt*>(substmt);
+ assert(SubStmt && isa<CompoundStmt>(SubStmt) && "Invalid action invocation!");
+ CompoundStmt *Compound = cast<CompoundStmt>(SubStmt);
+
+ // FIXME: there are a variety of strange constraints to enforce here, for
+ // example, it is not possible to goto into a stmt expression apparently.
+ // More semantic analysis is needed.
+
+ // FIXME: the last statement in the compount stmt has its value used. We
+ // should not warn about it being unused.
+
+ // If there are sub stmts in the compound stmt, take the type of the last one
+ // as the type of the stmtexpr.
+ QualType Ty = Context.VoidTy;
+
+ if (!Compound->body_empty())
+ if (Expr *LastExpr = dyn_cast<Expr>(Compound->body_back()))
+ Ty = LastExpr->getType();
+
+ return new StmtExpr(Compound, Ty, LPLoc, RPLoc);
+}
+
+Sema::ExprResult Sema::ActOnBuiltinOffsetOf(SourceLocation BuiltinLoc,
+ SourceLocation TypeLoc,
+ TypeTy *argty,
+ OffsetOfComponent *CompPtr,
+ unsigned NumComponents,
+ SourceLocation RPLoc) {
+ QualType ArgTy = QualType::getFromOpaquePtr(argty);
+ assert(!ArgTy.isNull() && "Missing type argument!");
+
+ // We must have at least one component that refers to the type, and the first
+ // one is known to be a field designator. Verify that the ArgTy represents
+ // a struct/union/class.
+ if (!ArgTy->isRecordType())
+ return Diag(TypeLoc, diag::err_offsetof_record_type,ArgTy.getAsString());
+
+ // Otherwise, create a compound literal expression as the base, and
+ // iteratively process the offsetof designators.
+ Expr *Res = new CompoundLiteralExpr(SourceLocation(), ArgTy, 0, false);
+
+ // offsetof with non-identifier designators (e.g. "offsetof(x, a.b[c])") are a
+ // GCC extension, diagnose them.
+ if (NumComponents != 1)
+ Diag(BuiltinLoc, diag::ext_offsetof_extended_field_designator,
+ SourceRange(CompPtr[1].LocStart, CompPtr[NumComponents-1].LocEnd));
+
+ for (unsigned i = 0; i != NumComponents; ++i) {
+ const OffsetOfComponent &OC = CompPtr[i];
+ if (OC.isBrackets) {
+ // Offset of an array sub-field. TODO: Should we allow vector elements?
+ const ArrayType *AT = Res->getType()->getAsArrayType();
+ if (!AT) {
+ delete Res;
+ return Diag(OC.LocEnd, diag::err_offsetof_array_type,
+ Res->getType().getAsString());
+ }
+
+ // FIXME: C++: Verify that operator[] isn't overloaded.
+
+ // C99 6.5.2.1p1
+ Expr *Idx = static_cast<Expr*>(OC.U.E);
+ if (!Idx->getType()->isIntegerType())
+ return Diag(Idx->getLocStart(), diag::err_typecheck_subscript,
+ Idx->getSourceRange());
+
+ Res = new ArraySubscriptExpr(Res, Idx, AT->getElementType(), OC.LocEnd);
+ continue;
+ }
+
+ const RecordType *RC = Res->getType()->getAsRecordType();
+ if (!RC) {
+ delete Res;
+ return Diag(OC.LocEnd, diag::err_offsetof_record_type,
+ Res->getType().getAsString());
+ }
+
+ // Get the decl corresponding to this.
+ RecordDecl *RD = RC->getDecl();
+ FieldDecl *MemberDecl = RD->getMember(OC.U.IdentInfo);
+ if (!MemberDecl)
+ return Diag(BuiltinLoc, diag::err_typecheck_no_member,
+ OC.U.IdentInfo->getName(),
+ SourceRange(OC.LocStart, OC.LocEnd));
+
+ // FIXME: C++: Verify that MemberDecl isn't a static field.
+ // FIXME: Verify that MemberDecl isn't a bitfield.
+ // MemberDecl->getType() doesn't get the right qualifiers, but it doesn't
+ // matter here.
+ Res = new MemberExpr(Res, false, MemberDecl, OC.LocEnd, MemberDecl->getType());
+ }
+
+ return new UnaryOperator(Res, UnaryOperator::OffsetOf, Context.getSizeType(),
+ BuiltinLoc);
+}
+
+
+Sema::ExprResult Sema::ActOnTypesCompatibleExpr(SourceLocation BuiltinLoc,
+ 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)");
+
+ return new TypesCompatibleExpr(Context.IntTy, BuiltinLoc, argT1, argT2,RPLoc);
+}
+
+Sema::ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc, ExprTy *cond,
+ ExprTy *expr1, ExprTy *expr2,
+ SourceLocation RPLoc) {
+ Expr *CondExpr = static_cast<Expr*>(cond);
+ Expr *LHSExpr = static_cast<Expr*>(expr1);
+ Expr *RHSExpr = static_cast<Expr*>(expr2);
+
+ assert((CondExpr && LHSExpr && RHSExpr) && "Missing type argument(s)");
+
+ // The conditional expression is required to be a constant expression.
+ llvm::APSInt condEval(32);
+ SourceLocation ExpLoc;
+ if (!CondExpr->isIntegerConstantExpr(condEval, Context, &ExpLoc))
+ return Diag(ExpLoc, diag::err_typecheck_choose_expr_requires_constant,
+ CondExpr->getSourceRange());
+
+ // If the condition is > zero, then the AST type is the same as the LSHExpr.
+ QualType resType = condEval.getZExtValue() ? LHSExpr->getType() :
+ RHSExpr->getType();
+ return new ChooseExpr(BuiltinLoc, CondExpr, LHSExpr, RHSExpr, resType, RPLoc);
+}
+
+/// ExprsMatchFnType - return true if the Exprs in array Args have
+/// QualTypes that match the QualTypes of the arguments of the FnType.
+/// The number of arguments has already been validated to match the number of
+/// arguments in FnType.
+static bool ExprsMatchFnType(Expr **Args, const FunctionTypeProto *FnType) {
+ unsigned NumParams = FnType->getNumArgs();
+ for (unsigned i = 0; i != NumParams; ++i)
+ if (Args[i]->getType().getCanonicalType() !=
+ FnType->getArgType(i).getCanonicalType())
+ return false;
+ return true;
+}
+
+Sema::ExprResult Sema::ActOnOverloadExpr(ExprTy **args, unsigned NumArgs,
+ SourceLocation *CommaLocs,
+ SourceLocation BuiltinLoc,
+ SourceLocation RParenLoc) {
+ // __builtin_overload requires at least 2 arguments
+ if (NumArgs < 2)
+ return Diag(RParenLoc, diag::err_typecheck_call_too_few_args,
+ SourceRange(BuiltinLoc, RParenLoc));
+
+ // 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.
+ Expr **Args = reinterpret_cast<Expr**>(args);
+ Expr *NParamsExpr = Args[0];
+ llvm::APSInt constEval(32);
+ SourceLocation ExpLoc;
+ if (!NParamsExpr->isIntegerConstantExpr(constEval, Context, &ExpLoc))
+ return Diag(ExpLoc, diag::err_overload_expr_requires_non_zero_constant,
+ NParamsExpr->getSourceRange());
+
+ // Verify that the number of parameters is > 0
+ unsigned NumParams = constEval.getZExtValue();
+ if (NumParams == 0)
+ return Diag(ExpLoc, diag::err_overload_expr_requires_non_zero_constant,
+ NParamsExpr->getSourceRange());
+ // Verify that we have at least 1 + NumParams arguments to the builtin.
+ if ((NumParams + 1) > NumArgs)
+ return Diag(RParenLoc, diag::err_typecheck_call_too_few_args,
+ SourceRange(BuiltinLoc, RParenLoc));
+
+ // Figure out the return type, by matching the args to one of the functions
+ // listed after the parameters.
+ OverloadExpr *OE = 0;
+ for (unsigned i = NumParams + 1; i < NumArgs; ++i) {
+ // UsualUnaryConversions will convert the function DeclRefExpr into a
+ // pointer to function.
+ Expr *Fn = UsualUnaryConversions(Args[i]);
+ FunctionTypeProto *FnType = 0;
+ if (const PointerType *PT = Fn->getType()->getAsPointerType()) {
+ QualType PointeeType = PT->getPointeeType().getCanonicalType();
+ FnType = dyn_cast<FunctionTypeProto>(PointeeType);
+ }
+
+ // 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))
+ return Diag(Fn->getExprLoc(), diag::err_overload_incorrect_fntype,
+ Fn->getSourceRange());
+
+ // Scan the parameter list for the FunctionType, checking the QualType of
+ // each parameter against the QualTypes of the arguments to the builtin.
+ // If they match, return a new OverloadExpr.
+ if (ExprsMatchFnType(Args+1, FnType)) {
+ if (OE)
+ return Diag(Fn->getExprLoc(), diag::err_overload_multiple_match,
+ OE->getFn()->getSourceRange());
+ // Remember our match, and continue processing the remaining arguments
+ // to catch any errors.
+ OE = new OverloadExpr(Args, NumArgs, i, FnType->getResultType(),
+ BuiltinLoc, RParenLoc);
+ }
+ }
+ // Return the newly created OverloadExpr node, if we succeded in matching
+ // exactly one of the candidate functions.
+ if (OE)
+ return OE;
+
+ // If we didn't find a matching function Expr in the __builtin_overload list
+ // the return an error.
+ std::string typeNames;
+ for (unsigned i = 0; i != NumParams; ++i) {
+ if (i != 0) typeNames += ", ";
+ typeNames += Args[i+1]->getType().getAsString();
+ }
+
+ return Diag(BuiltinLoc, diag::err_overload_no_match, typeNames,
+ SourceRange(BuiltinLoc, RParenLoc));
+}
+
+Sema::ExprResult Sema::ActOnVAArg(SourceLocation BuiltinLoc,
+ ExprTy *expr, TypeTy *type,
+ SourceLocation RPLoc) {
+ Expr *E = static_cast<Expr*>(expr);
+ QualType T = QualType::getFromOpaquePtr(type);
+
+ InitBuiltinVaListType();
+
+ if (CheckAssignmentConstraints(Context.getBuiltinVaListType(), E->getType())
+ != Compatible)
+ return Diag(E->getLocStart(),
+ diag::err_first_argument_to_va_arg_not_of_type_va_list,
+ E->getType().getAsString(),
+ E->getSourceRange());
+
+ // FIXME: Warn if a non-POD type is passed in.
+
+ return new VAArgExpr(BuiltinLoc, E, T, RPLoc);
+}
+
+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;
+ case PointerToInt:
+ DiagKind = diag::ext_typecheck_convert_pointer_int;
+ break;
+ case IntToPointer:
+ DiagKind = diag::ext_typecheck_convert_int_pointer;
+ break;
+ case IncompatiblePointer:
+ DiagKind = diag::ext_typecheck_convert_incompatible_pointer;
+ break;
+ case FunctionVoidPointer:
+ DiagKind = diag::ext_typecheck_convert_pointer_void_func;
+ break;
+ case CompatiblePointerDiscardsQualifiers:
+ DiagKind = diag::ext_typecheck_convert_discards_qualifiers;
+ break;
+ case Incompatible:
+ DiagKind = diag::err_typecheck_convert_incompatible;
+ isInvalid = true;
+ break;
+ }
+
+ Diag(Loc, DiagKind, DstType.getAsString(), SrcType.getAsString(), Flavor,
+ SrcExpr->getSourceRange());
+ return isInvalid;
+}
+
OpenPOWER on IntegriCloud