forked from OSchip/llvm-project
Bug #:
Submitted by: Reviewed by: Type Checking...round 2. This checkin "breaks" parsing carbon.h. I imagine that this will be true for the next week or so. Nevertheless, this round of changes includes the following: - Hacked various Expr classes to pass the appropriate TypeRef. Still have a few more classes to touch. - Implement type checking for ParseArraySubscriptExpr and ParseMemberReferenceExpr. - Added a debug hook to derive the class name for Stmt/Expr nodes. Currently a linear search...could easily optimize if important. - Changed the name of TaggedType->TagType. Now we have TagType and TagDecl (which are easier to remember). - Fixed a bug in StringLiteral conversion I did a couple weeks ago. hadError was not initialized (oops). - changed Sema::Diag to return true. This streamlines the type checking code considerably. - Added many diagnositics. This should be it! llvm-svn: 39361
This commit is contained in:
parent
26c8ea5fab
commit
f1e53698a4
|
@ -55,7 +55,7 @@ void ASTContext::PrintStats() const {
|
|||
++NumFunctionP;
|
||||
else if (isa<TypedefType>(T))
|
||||
++NumTypeName;
|
||||
else if (TaggedType *TT = dyn_cast<TaggedType>(T)) {
|
||||
else if (TagType *TT = dyn_cast<TagType>(T)) {
|
||||
++NumTagged;
|
||||
switch (TT->getDecl()->getKind()) {
|
||||
default: assert(0 && "Unknown tagged type!");
|
||||
|
@ -280,7 +280,7 @@ TypeRef ASTContext::getTagDeclType(TagDecl *Decl) {
|
|||
// The decl stores the type cache.
|
||||
if (Decl->TypeForDecl) return Decl->TypeForDecl;
|
||||
|
||||
Types.push_back(Decl->TypeForDecl = new TaggedType(Decl, 0));
|
||||
Types.push_back(Decl->TypeForDecl = new TagType(Decl, 0));
|
||||
return Types.back();
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,8 @@ using namespace clang;
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
StringLiteral::StringLiteral(const char *strData, unsigned byteLength,
|
||||
bool Wide) : Expr(StringLiteralClass) {
|
||||
bool Wide, TypeRef t) :
|
||||
Expr(StringLiteralClass, t) {
|
||||
// OPTIMIZE: could allocate this appended to the StringLiteral.
|
||||
char *AStrData = new char[byteLength];
|
||||
memcpy(AStrData, strData, byteLength);
|
||||
|
@ -73,7 +74,7 @@ const char *UnaryOperator::getOpcodeStr(Opcode Op) {
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
CallExpr::CallExpr(Expr *fn, Expr **args, unsigned numargs)
|
||||
: Expr(CallExprClass), Fn(fn), NumArgs(numargs) {
|
||||
: Expr(CallExprClass, fn->getTypeRef()), Fn(fn), NumArgs(numargs) {
|
||||
Args = new Expr*[numargs];
|
||||
for (unsigned i = 0; i != numargs; ++i)
|
||||
Args[i] = args[i];
|
||||
|
|
|
@ -26,12 +26,14 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, std::vector<Decl*> &prevInGroup)
|
|||
// Helper functions.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg) {
|
||||
bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg) {
|
||||
PP.Diag(Loc, DiagID, Msg);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Sema::Diag(const LexerToken &Tok, unsigned DiagID, const std::string &M) {
|
||||
bool Sema::Diag(const LexerToken &Tok, unsigned DiagID, const std::string &M) {
|
||||
Diag(Tok.getLocation(), DiagID, M);
|
||||
return true;
|
||||
}
|
||||
|
||||
const LangOptions &Sema::getLangOptions() const {
|
||||
|
|
|
@ -53,9 +53,10 @@ public:
|
|||
|
||||
const LangOptions &getLangOptions() const;
|
||||
|
||||
void Diag(SourceLocation Loc, unsigned DiagID,
|
||||
/// always returns true, which simplifies error handling (i.e. less code).
|
||||
bool Diag(SourceLocation Loc, unsigned DiagID,
|
||||
const std::string &Msg = std::string());
|
||||
void Diag(const LexerToken &Tok, unsigned DiagID,
|
||||
bool Diag(const LexerToken &Tok, unsigned DiagID,
|
||||
const std::string &M = std::string());
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
@ -220,6 +221,8 @@ public:
|
|||
virtual ExprResult ParseCXXBoolLiteral(SourceLocation OpLoc,
|
||||
tok::TokenKind Kind);
|
||||
private:
|
||||
Expr *ImplicitConversion(Expr *E); // C99 6.3
|
||||
|
||||
/// type checking binary operators (subroutines of ParseBinOp).
|
||||
void CheckMultiplicativeOperands(Expr *op1, Expr *op2); // C99 6.5.5
|
||||
void CheckAdditiveOperands(Expr *op1, Expr *op2); // C99 6.5.6
|
||||
|
|
|
@ -42,11 +42,14 @@ Sema::ParseStringLiteral(const LexerToken *StringToks, unsigned NumStringToks) {
|
|||
SmallVector<SourceLocation, 4> StringTokLocs;
|
||||
for (unsigned i = 0; i != NumStringToks; ++i)
|
||||
StringTokLocs.push_back(StringToks[i].getLocation());
|
||||
|
||||
|
||||
// FIXME: handle wchar_t
|
||||
TypeRef t = Context.getPointerType(Context.CharTy);
|
||||
|
||||
// FIXME: use factory.
|
||||
// Pass &StringTokLocs[0], StringTokLocs.size() to factory!
|
||||
return new StringLiteral(Literal.GetString(), Literal.GetStringLength(),
|
||||
Literal.AnyWide);
|
||||
Literal.AnyWide, t);
|
||||
}
|
||||
|
||||
|
||||
|
@ -63,22 +66,20 @@ Sema::ExprResult Sema::ParseIdentifierExpr(Scope *S, SourceLocation Loc,
|
|||
// in C90, extension in C99).
|
||||
if (HasTrailingLParen &&
|
||||
// Not in C++.
|
||||
!getLangOptions().CPlusPlus) {
|
||||
!getLangOptions().CPlusPlus)
|
||||
D = ImplicitlyDefineFunction(Loc, II, S);
|
||||
} else {
|
||||
else
|
||||
// If this name wasn't predeclared and if this is not a function call,
|
||||
// diagnose the problem.
|
||||
Diag(Loc, diag::err_undeclared_var_use, II.getName());
|
||||
return true;
|
||||
}
|
||||
return Diag(Loc, diag::err_undeclared_var_use, II.getName());
|
||||
}
|
||||
|
||||
if (isa<TypedefDecl>(D)) {
|
||||
Diag(Loc, diag::err_unexpected_typedef, II.getName());
|
||||
return true;
|
||||
}
|
||||
|
||||
return new DeclRefExpr(D);
|
||||
if (ObjectDecl *OD = dyn_cast<ObjectDecl>(D)) {
|
||||
return new DeclRefExpr(OD);
|
||||
} else if (isa<TypedefDecl>(D))
|
||||
return Diag(Loc, diag::err_unexpected_typedef, II.getName());
|
||||
|
||||
assert(0 && "Invalid decl");
|
||||
}
|
||||
|
||||
Sema::ExprResult Sema::ParseSimplePrimaryExpr(SourceLocation Loc,
|
||||
|
@ -136,7 +137,8 @@ Action::ExprResult Sema::ParseNumericConstant(const LexerToken &Tok) {
|
|||
return new IntegerLiteral(val, t);
|
||||
}
|
||||
} else if (Literal.isFloatingLiteral()) {
|
||||
// TODO: add floating point processing...
|
||||
// FIXME: fill in the value and compute the real type...
|
||||
return new FloatingLiteral(7.7, Context.FloatTy);
|
||||
}
|
||||
return ExprResult(true);
|
||||
}
|
||||
|
@ -199,7 +201,7 @@ ParseSizeOfAlignOfTypeExpr(SourceLocation OpLoc, bool isSizeof,
|
|||
return new IntegerLiteral(0, Context.IntTy);
|
||||
}
|
||||
|
||||
return new SizeOfAlignOfTypeExpr(isSizeof, ArgTy);
|
||||
return new SizeOfAlignOfTypeExpr(isSizeof, ArgTy, Context.IntTy);
|
||||
}
|
||||
|
||||
|
||||
|
@ -219,13 +221,59 @@ Action::ExprResult Sema::ParsePostfixUnaryOp(SourceLocation OpLoc,
|
|||
Action::ExprResult Sema::
|
||||
ParseArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc,
|
||||
ExprTy *Idx, SourceLocation RLoc) {
|
||||
return new ArraySubscriptExpr((Expr*)Base, (Expr*)Idx);
|
||||
TypeRef t1 = ((Expr *)Base)->getTypeRef();
|
||||
TypeRef t2 = ((Expr *)Idx)->getTypeRef();
|
||||
|
||||
assert(!t1.isNull() && "no type for array base expression");
|
||||
assert(!t1.isNull() && "no type for array index expression");
|
||||
|
||||
// In C, 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.
|
||||
|
||||
TypeRef baseType, indexType;
|
||||
if (isa<ArrayType>(t1) || isa<PointerType>(t1)) {
|
||||
baseType = t1;
|
||||
indexType = t2;
|
||||
} else if (isa<ArrayType>(t2) || isa<PointerType>(t2)) { // uncommon case
|
||||
baseType = t2;
|
||||
indexType = t1;
|
||||
} else
|
||||
return Diag(LLoc, diag::err_typecheck_subscript_value);
|
||||
|
||||
if (indexType->isIntegralType())
|
||||
return new ArraySubscriptExpr((Expr*)Base, (Expr*)Idx, baseType);
|
||||
else
|
||||
return Diag(LLoc, diag::err_typecheck_subscript);
|
||||
}
|
||||
|
||||
Action::ExprResult Sema::
|
||||
ParseMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind, SourceLocation MemberLoc,
|
||||
IdentifierInfo &Member) {
|
||||
TypeRef BT = ((Expr *)Base)->getTypeRef();
|
||||
|
||||
assert(!BT.isNull() && "no type for member expression");
|
||||
|
||||
if (OpKind == tok::arrow) {
|
||||
if (PointerType *PT = dyn_cast<PointerType>(BT))
|
||||
BT = PT->getPointeeType();
|
||||
else
|
||||
return Diag(OpLoc, diag::err_typecheck_member_reference_arrow);
|
||||
}
|
||||
RecordDecl *RD;
|
||||
|
||||
// derive the structure/union definition from the type.
|
||||
if (BT->isStructureType() || BT->isUnionType()) {
|
||||
TagDecl *TD = cast<TagType>(BT)->getDecl();
|
||||
if (BT->isIncompleteType())
|
||||
return Diag(OpLoc, diag::err_typecheck_incomplete_tag, TD->getName());
|
||||
if (!(RD = dyn_cast<RecordDecl>(TD)))
|
||||
return Diag(OpLoc, diag::err_typecheck_internal_error);
|
||||
} else
|
||||
return Diag(OpLoc, diag::err_typecheck_member_reference_structUnion);
|
||||
|
||||
Decl *MemberDecl = 0;
|
||||
// TODO: Look up MemberDecl.
|
||||
return new MemberExpr((Expr*)Base, OpKind == tok::arrow, MemberDecl);
|
||||
|
@ -288,6 +336,10 @@ Action::ExprResult Sema::ParseBinOp(SourceLocation TokLoc, tok::TokenKind Kind,
|
|||
case tok::pipeequal: Opc = BinaryOperator::OrAssign; break;
|
||||
case tok::comma: Opc = BinaryOperator::Comma; break;
|
||||
}
|
||||
|
||||
// perform implicit conversions (C99 6.3)
|
||||
Expr *e1 = ImplicitConversion((Expr*)LHS);
|
||||
Expr *e2 = ImplicitConversion((Expr*)RHS);
|
||||
|
||||
if (BinaryOperator::isMultiplicativeOp(Opc))
|
||||
CheckMultiplicativeOperands((Expr*)LHS, (Expr*)RHS);
|
||||
|
@ -316,6 +368,15 @@ Action::ExprResult Sema::ParseConditionalOp(SourceLocation QuestionLoc,
|
|||
return new ConditionalOperator((Expr*)Cond, (Expr*)LHS, (Expr*)RHS);
|
||||
}
|
||||
|
||||
Expr *Sema::ImplicitConversion(Expr *E) {
|
||||
#if 0
|
||||
TypeRef t = E->getTypeRef();
|
||||
if (t != 0) t.dump();
|
||||
else printf("no type for expr %s\n", E->getStmtClassName());
|
||||
#endif
|
||||
return E;
|
||||
}
|
||||
|
||||
void Sema::CheckMultiplicativeOperands(Expr *op1, Expr *op2) {
|
||||
}
|
||||
|
||||
|
|
|
@ -23,3 +23,21 @@ void CLASS::visit(StmtVisitor &V) { return V.Visit##CLASS(this); }
|
|||
|
||||
STMT(0, Stmt, )
|
||||
#include "clang/AST/StmtNodes.def"
|
||||
|
||||
static struct StmtClassNameTable {
|
||||
int enumValue;
|
||||
const char *className;
|
||||
} sNames[] = {
|
||||
#define STMT(N, CLASS, PARENT) { N, #CLASS },
|
||||
#include "clang/AST/StmtNodes.def"
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
const char *Stmt::getStmtClassName() const {
|
||||
for (int i = 0; sNames[i].className; i++) {
|
||||
if (sClass == sNames[i].enumValue)
|
||||
return sNames[i].className;
|
||||
}
|
||||
return 0; // should never happen....
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ bool Type::isArrayType() const {
|
|||
}
|
||||
|
||||
bool Type::isStructureType() const {
|
||||
if (const TaggedType *TT = dyn_cast<TaggedType>(CanonicalType)) {
|
||||
if (const TagType *TT = dyn_cast<TagType>(CanonicalType)) {
|
||||
if (TT->getDecl()->getKind() == Decl::Struct)
|
||||
return true;
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ bool Type::isStructureType() const {
|
|||
}
|
||||
|
||||
bool Type::isUnionType() const {
|
||||
if (const TaggedType *TT = dyn_cast<TaggedType>(CanonicalType)) {
|
||||
if (const TagType *TT = dyn_cast<TagType>(CanonicalType)) {
|
||||
if (TT->getDecl()->getKind() == Decl::Union)
|
||||
return true;
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ bool Type::isIntegralType() const {
|
|||
return BT->getKind() >= BuiltinType::Bool &&
|
||||
BT->getKind() <= BuiltinType::ULongLong;
|
||||
case Tagged:
|
||||
const TaggedType *TT = static_cast<TaggedType*>(CanonicalType);
|
||||
const TagType *TT = static_cast<TagType*>(CanonicalType);
|
||||
if (TT->getDecl()->getKind() == Decl::Enum)
|
||||
return true;
|
||||
return false;
|
||||
|
@ -110,7 +110,7 @@ bool Type::isAggregateType() const {
|
|||
case Array:
|
||||
return true;
|
||||
case Tagged:
|
||||
const TaggedType *TT = static_cast<TaggedType*>(CanonicalType);
|
||||
const TagType *TT = static_cast<TagType*>(CanonicalType);
|
||||
if (TT->getDecl()->getKind() == Decl::Struct)
|
||||
return true;
|
||||
return true;
|
||||
|
@ -131,7 +131,7 @@ bool Type::isIncompleteType() const {
|
|||
case Tagged:
|
||||
// A tagged type (struct/union/enum/class) is incomplete if the decl is a
|
||||
// forward declaration, but not a full definition (C99 6.2.5p22).
|
||||
return !cast<TaggedType>(CanonicalType)->getDecl()->isDefinition();
|
||||
return !cast<TagType>(CanonicalType)->getDecl()->isDefinition();
|
||||
case Array:
|
||||
// An array of unknown size is an incomplete type (C99 6.2.5p22).
|
||||
return cast<ArrayType>(CanonicalType)->getSize() == 0;
|
||||
|
@ -179,7 +179,7 @@ void FunctionTypeProto::Profile(FoldingSetNodeID &ID) {
|
|||
|
||||
|
||||
bool RecordType::classof(const Type *T) {
|
||||
if (const TaggedType *TT = dyn_cast<TaggedType>(T))
|
||||
if (const TagType *TT = dyn_cast<TagType>(T))
|
||||
return isa<RecordDecl>(TT->getDecl());
|
||||
return false;
|
||||
}
|
||||
|
@ -304,7 +304,7 @@ void TypedefType::getAsString(std::string &InnerString) const {
|
|||
InnerString = getDecl()->getIdentifier()->getName() + InnerString;
|
||||
}
|
||||
|
||||
void TaggedType::getAsString(std::string &InnerString) const {
|
||||
void TagType::getAsString(std::string &InnerString) const {
|
||||
if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
|
||||
InnerString = ' ' + InnerString;
|
||||
|
||||
|
|
|
@ -322,6 +322,8 @@ StringLiteralParser(const LexerToken *StringToks, unsigned NumStringToks,
|
|||
SizeBound = StringToks[0].getLength()-2; // -2 for "".
|
||||
AnyWide = StringToks[0].getKind() == tok::wide_string_literal;
|
||||
|
||||
hadError = false;
|
||||
|
||||
// The common case is that there is only one string fragment.
|
||||
for (unsigned i = 1; i != NumStringToks; ++i) {
|
||||
// The string could be shorter than this if it needs cleaning, but this is a
|
||||
|
|
|
@ -608,7 +608,7 @@ Parser::ExprResult Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
|
|||
|
||||
if (!LHS.isInvalid && !Idx.isInvalid && Tok.getKind() == tok::r_square)
|
||||
LHS = Actions.ParseArraySubscriptExpr(LHS.Val, Loc, Idx.Val, RLoc);
|
||||
else
|
||||
else
|
||||
LHS = ExprResult(true);
|
||||
|
||||
// Match the ']'.
|
||||
|
|
|
@ -26,12 +26,14 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, std::vector<Decl*> &prevInGroup)
|
|||
// Helper functions.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg) {
|
||||
bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg) {
|
||||
PP.Diag(Loc, DiagID, Msg);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Sema::Diag(const LexerToken &Tok, unsigned DiagID, const std::string &M) {
|
||||
bool Sema::Diag(const LexerToken &Tok, unsigned DiagID, const std::string &M) {
|
||||
Diag(Tok.getLocation(), DiagID, M);
|
||||
return true;
|
||||
}
|
||||
|
||||
const LangOptions &Sema::getLangOptions() const {
|
||||
|
|
|
@ -53,9 +53,10 @@ public:
|
|||
|
||||
const LangOptions &getLangOptions() const;
|
||||
|
||||
void Diag(SourceLocation Loc, unsigned DiagID,
|
||||
/// always returns true, which simplifies error handling (i.e. less code).
|
||||
bool Diag(SourceLocation Loc, unsigned DiagID,
|
||||
const std::string &Msg = std::string());
|
||||
void Diag(const LexerToken &Tok, unsigned DiagID,
|
||||
bool Diag(const LexerToken &Tok, unsigned DiagID,
|
||||
const std::string &M = std::string());
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
@ -220,6 +221,8 @@ public:
|
|||
virtual ExprResult ParseCXXBoolLiteral(SourceLocation OpLoc,
|
||||
tok::TokenKind Kind);
|
||||
private:
|
||||
Expr *ImplicitConversion(Expr *E); // C99 6.3
|
||||
|
||||
/// type checking binary operators (subroutines of ParseBinOp).
|
||||
void CheckMultiplicativeOperands(Expr *op1, Expr *op2); // C99 6.5.5
|
||||
void CheckAdditiveOperands(Expr *op1, Expr *op2); // C99 6.5.6
|
||||
|
|
|
@ -42,11 +42,14 @@ Sema::ParseStringLiteral(const LexerToken *StringToks, unsigned NumStringToks) {
|
|||
SmallVector<SourceLocation, 4> StringTokLocs;
|
||||
for (unsigned i = 0; i != NumStringToks; ++i)
|
||||
StringTokLocs.push_back(StringToks[i].getLocation());
|
||||
|
||||
|
||||
// FIXME: handle wchar_t
|
||||
TypeRef t = Context.getPointerType(Context.CharTy);
|
||||
|
||||
// FIXME: use factory.
|
||||
// Pass &StringTokLocs[0], StringTokLocs.size() to factory!
|
||||
return new StringLiteral(Literal.GetString(), Literal.GetStringLength(),
|
||||
Literal.AnyWide);
|
||||
Literal.AnyWide, t);
|
||||
}
|
||||
|
||||
|
||||
|
@ -63,22 +66,20 @@ Sema::ExprResult Sema::ParseIdentifierExpr(Scope *S, SourceLocation Loc,
|
|||
// in C90, extension in C99).
|
||||
if (HasTrailingLParen &&
|
||||
// Not in C++.
|
||||
!getLangOptions().CPlusPlus) {
|
||||
!getLangOptions().CPlusPlus)
|
||||
D = ImplicitlyDefineFunction(Loc, II, S);
|
||||
} else {
|
||||
else
|
||||
// If this name wasn't predeclared and if this is not a function call,
|
||||
// diagnose the problem.
|
||||
Diag(Loc, diag::err_undeclared_var_use, II.getName());
|
||||
return true;
|
||||
}
|
||||
return Diag(Loc, diag::err_undeclared_var_use, II.getName());
|
||||
}
|
||||
|
||||
if (isa<TypedefDecl>(D)) {
|
||||
Diag(Loc, diag::err_unexpected_typedef, II.getName());
|
||||
return true;
|
||||
}
|
||||
|
||||
return new DeclRefExpr(D);
|
||||
if (ObjectDecl *OD = dyn_cast<ObjectDecl>(D)) {
|
||||
return new DeclRefExpr(OD);
|
||||
} else if (isa<TypedefDecl>(D))
|
||||
return Diag(Loc, diag::err_unexpected_typedef, II.getName());
|
||||
|
||||
assert(0 && "Invalid decl");
|
||||
}
|
||||
|
||||
Sema::ExprResult Sema::ParseSimplePrimaryExpr(SourceLocation Loc,
|
||||
|
@ -136,7 +137,8 @@ Action::ExprResult Sema::ParseNumericConstant(const LexerToken &Tok) {
|
|||
return new IntegerLiteral(val, t);
|
||||
}
|
||||
} else if (Literal.isFloatingLiteral()) {
|
||||
// TODO: add floating point processing...
|
||||
// FIXME: fill in the value and compute the real type...
|
||||
return new FloatingLiteral(7.7, Context.FloatTy);
|
||||
}
|
||||
return ExprResult(true);
|
||||
}
|
||||
|
@ -199,7 +201,7 @@ ParseSizeOfAlignOfTypeExpr(SourceLocation OpLoc, bool isSizeof,
|
|||
return new IntegerLiteral(0, Context.IntTy);
|
||||
}
|
||||
|
||||
return new SizeOfAlignOfTypeExpr(isSizeof, ArgTy);
|
||||
return new SizeOfAlignOfTypeExpr(isSizeof, ArgTy, Context.IntTy);
|
||||
}
|
||||
|
||||
|
||||
|
@ -219,13 +221,59 @@ Action::ExprResult Sema::ParsePostfixUnaryOp(SourceLocation OpLoc,
|
|||
Action::ExprResult Sema::
|
||||
ParseArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc,
|
||||
ExprTy *Idx, SourceLocation RLoc) {
|
||||
return new ArraySubscriptExpr((Expr*)Base, (Expr*)Idx);
|
||||
TypeRef t1 = ((Expr *)Base)->getTypeRef();
|
||||
TypeRef t2 = ((Expr *)Idx)->getTypeRef();
|
||||
|
||||
assert(!t1.isNull() && "no type for array base expression");
|
||||
assert(!t1.isNull() && "no type for array index expression");
|
||||
|
||||
// In C, 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.
|
||||
|
||||
TypeRef baseType, indexType;
|
||||
if (isa<ArrayType>(t1) || isa<PointerType>(t1)) {
|
||||
baseType = t1;
|
||||
indexType = t2;
|
||||
} else if (isa<ArrayType>(t2) || isa<PointerType>(t2)) { // uncommon case
|
||||
baseType = t2;
|
||||
indexType = t1;
|
||||
} else
|
||||
return Diag(LLoc, diag::err_typecheck_subscript_value);
|
||||
|
||||
if (indexType->isIntegralType())
|
||||
return new ArraySubscriptExpr((Expr*)Base, (Expr*)Idx, baseType);
|
||||
else
|
||||
return Diag(LLoc, diag::err_typecheck_subscript);
|
||||
}
|
||||
|
||||
Action::ExprResult Sema::
|
||||
ParseMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind, SourceLocation MemberLoc,
|
||||
IdentifierInfo &Member) {
|
||||
TypeRef BT = ((Expr *)Base)->getTypeRef();
|
||||
|
||||
assert(!BT.isNull() && "no type for member expression");
|
||||
|
||||
if (OpKind == tok::arrow) {
|
||||
if (PointerType *PT = dyn_cast<PointerType>(BT))
|
||||
BT = PT->getPointeeType();
|
||||
else
|
||||
return Diag(OpLoc, diag::err_typecheck_member_reference_arrow);
|
||||
}
|
||||
RecordDecl *RD;
|
||||
|
||||
// derive the structure/union definition from the type.
|
||||
if (BT->isStructureType() || BT->isUnionType()) {
|
||||
TagDecl *TD = cast<TagType>(BT)->getDecl();
|
||||
if (BT->isIncompleteType())
|
||||
return Diag(OpLoc, diag::err_typecheck_incomplete_tag, TD->getName());
|
||||
if (!(RD = dyn_cast<RecordDecl>(TD)))
|
||||
return Diag(OpLoc, diag::err_typecheck_internal_error);
|
||||
} else
|
||||
return Diag(OpLoc, diag::err_typecheck_member_reference_structUnion);
|
||||
|
||||
Decl *MemberDecl = 0;
|
||||
// TODO: Look up MemberDecl.
|
||||
return new MemberExpr((Expr*)Base, OpKind == tok::arrow, MemberDecl);
|
||||
|
@ -288,6 +336,10 @@ Action::ExprResult Sema::ParseBinOp(SourceLocation TokLoc, tok::TokenKind Kind,
|
|||
case tok::pipeequal: Opc = BinaryOperator::OrAssign; break;
|
||||
case tok::comma: Opc = BinaryOperator::Comma; break;
|
||||
}
|
||||
|
||||
// perform implicit conversions (C99 6.3)
|
||||
Expr *e1 = ImplicitConversion((Expr*)LHS);
|
||||
Expr *e2 = ImplicitConversion((Expr*)RHS);
|
||||
|
||||
if (BinaryOperator::isMultiplicativeOp(Opc))
|
||||
CheckMultiplicativeOperands((Expr*)LHS, (Expr*)RHS);
|
||||
|
@ -316,6 +368,15 @@ Action::ExprResult Sema::ParseConditionalOp(SourceLocation QuestionLoc,
|
|||
return new ConditionalOperator((Expr*)Cond, (Expr*)LHS, (Expr*)RHS);
|
||||
}
|
||||
|
||||
Expr *Sema::ImplicitConversion(Expr *E) {
|
||||
#if 0
|
||||
TypeRef t = E->getTypeRef();
|
||||
if (t != 0) t.dump();
|
||||
else printf("no type for expr %s\n", E->getStmtClassName());
|
||||
#endif
|
||||
return E;
|
||||
}
|
||||
|
||||
void Sema::CheckMultiplicativeOperands(Expr *op1, Expr *op2) {
|
||||
}
|
||||
|
||||
|
|
|
@ -59,11 +59,12 @@ private:
|
|||
///
|
||||
Decl *Next;
|
||||
|
||||
public:
|
||||
protected:
|
||||
Decl(Kind DK, SourceLocation L, IdentifierInfo *Id)
|
||||
: DeclKind(DK), Loc(L), Identifier(Id), Next(0) {}
|
||||
virtual ~Decl();
|
||||
|
||||
public:
|
||||
IdentifierInfo *getIdentifier() const { return Identifier; }
|
||||
SourceLocation getLocation() const { return Loc; }
|
||||
void setLocation(SourceLocation L) { Loc = L; }
|
||||
|
@ -106,6 +107,8 @@ protected:
|
|||
ObjectDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, TypeRef T,
|
||||
StorageClass S = None): Decl(DK, L, Id), DeclType(T), SClass(S) {}
|
||||
public:
|
||||
// FIXME: should rename to getTypeRef/getCanonicalTypeRef to distinguish
|
||||
// TypeRef's from Type's...
|
||||
TypeRef getType() const { return DeclType; }
|
||||
TypeRef getCanonicalType() const { return DeclType.getCanonicalType(); }
|
||||
StorageClass getStorageClass() const { return SClass; }
|
||||
|
@ -185,7 +188,7 @@ public:
|
|||
/// EnumConstantDecl - An instance of this object exists for each enum constant
|
||||
/// that is defined. For example, in "enum X {a,b}", each of a/b are
|
||||
/// EnumConstantDecl's, X is an instance of EnumDecl, and the type of a/b is a
|
||||
/// TaggedType for the X EnumDecl.
|
||||
/// TagType for the X EnumDecl.
|
||||
class EnumConstantDecl : public ObjectDecl {
|
||||
public:
|
||||
// FIXME: Capture value info.
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "clang/AST/Stmt.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace clang {
|
||||
|
@ -27,10 +28,15 @@ namespace clang {
|
|||
/// is required.
|
||||
///
|
||||
class Expr : public Stmt {
|
||||
TypeRef Type;
|
||||
public:
|
||||
Expr(StmtClass SC, TypeRef T=0) : Stmt(SC), Type(T) {}
|
||||
TypeRef TR;
|
||||
protected:
|
||||
Expr(StmtClass SC, TypeRef T=0) : Stmt(SC), TR(T) {}
|
||||
~Expr() {}
|
||||
public:
|
||||
// FIXME: the return type of getType is inconsistent with ObjectDecl.
|
||||
// this is confusing and needs to be reconciled (by making one conform).
|
||||
Type *getType() const { return TR.getTypePtr(); }
|
||||
TypeRef getTypeRef() const { return TR; }
|
||||
|
||||
virtual void visit(StmtVisitor &Visitor);
|
||||
static bool classof(const Stmt *T) {
|
||||
|
@ -47,9 +53,9 @@ public:
|
|||
/// DeclRefExpr - [C99 6.5.1p2] - A reference to a declared variable, function,
|
||||
/// enum, etc.
|
||||
class DeclRefExpr : public Expr {
|
||||
Decl *D;
|
||||
ObjectDecl *D;
|
||||
public:
|
||||
DeclRefExpr(Decl *d) : Expr(DeclRefExprClass), D(d) {}
|
||||
DeclRefExpr(ObjectDecl *d) : Expr(DeclRefExprClass, d->getType()), D(d) {}
|
||||
|
||||
Decl *getDecl() const { return D; }
|
||||
|
||||
|
@ -77,8 +83,10 @@ public:
|
|||
};
|
||||
|
||||
class FloatingLiteral : public Expr {
|
||||
float Value; // FIXME
|
||||
public:
|
||||
FloatingLiteral() : Expr(FloatingLiteralClass) {}
|
||||
FloatingLiteral(float value, TypeRef type) :
|
||||
Expr(FloatingLiteralClass, type), Value(value) {}
|
||||
virtual void visit(StmtVisitor &Visitor);
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == FloatingLiteralClass;
|
||||
|
@ -91,7 +99,7 @@ class StringLiteral : public Expr {
|
|||
unsigned ByteLength;
|
||||
bool IsWide;
|
||||
public:
|
||||
StringLiteral(const char *strData, unsigned byteLength, bool Wide);
|
||||
StringLiteral(const char *strData, unsigned byteLength, bool Wide, TypeRef t);
|
||||
virtual ~StringLiteral();
|
||||
|
||||
const char *getStrData() const { return StrData; }
|
||||
|
@ -174,9 +182,9 @@ class SizeOfAlignOfTypeExpr : public Expr {
|
|||
bool isSizeof; // true if sizeof, false if alignof.
|
||||
TypeRef Ty;
|
||||
public:
|
||||
SizeOfAlignOfTypeExpr(bool issizeof, TypeRef ty) :
|
||||
Expr(SizeOfAlignOfTypeExprClass),
|
||||
isSizeof(issizeof), Ty(ty) {}
|
||||
SizeOfAlignOfTypeExpr(bool issizeof, TypeRef argType, TypeRef resultType) :
|
||||
Expr(SizeOfAlignOfTypeExprClass, resultType),
|
||||
isSizeof(issizeof), Ty(argType) {}
|
||||
|
||||
bool isSizeOf() const { return isSizeof; }
|
||||
TypeRef getArgumentType() const { return Ty; }
|
||||
|
@ -196,8 +204,8 @@ public:
|
|||
class ArraySubscriptExpr : public Expr {
|
||||
Expr *Base, *Idx;
|
||||
public:
|
||||
ArraySubscriptExpr(Expr *base, Expr *idx) :
|
||||
Expr(ArraySubscriptExprClass),
|
||||
ArraySubscriptExpr(Expr *base, Expr *idx, TypeRef t) :
|
||||
Expr(ArraySubscriptExprClass, t),
|
||||
Base(base), Idx(idx) {}
|
||||
|
||||
Expr *getBase() { return Base; }
|
||||
|
|
|
@ -43,6 +43,7 @@ public:
|
|||
virtual ~Stmt() {}
|
||||
|
||||
StmtClass getStmtClass() const { return sClass; }
|
||||
const char *getStmtClassName() const;
|
||||
|
||||
void dump() const;
|
||||
void print(std::ostream &OS) const;
|
||||
|
|
|
@ -424,9 +424,9 @@ public:
|
|||
};
|
||||
|
||||
|
||||
class TaggedType : public Type {
|
||||
class TagType : public Type {
|
||||
TagDecl *Decl;
|
||||
TaggedType(TagDecl *D, Type *can) : Type(Tagged, can), Decl(D) {}
|
||||
TagType(TagDecl *D, Type *can) : Type(Tagged, can), Decl(D) {}
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
public:
|
||||
|
||||
|
@ -435,17 +435,17 @@ public:
|
|||
virtual void getAsString(std::string &InnerString) const;
|
||||
|
||||
static bool classof(const Type *T) { return T->getTypeClass() == Tagged; }
|
||||
static bool classof(const TaggedType *) { return true; }
|
||||
static bool classof(const TagType *) { return true; }
|
||||
};
|
||||
|
||||
/// RecordType - This is a helper class that allows the use of isa/cast/dyncast
|
||||
/// to detect TaggedType objects of structs/unions/classes.
|
||||
class RecordType : public TaggedType {
|
||||
/// to detect TagType objects of structs/unions/classes.
|
||||
class RecordType : public TagType {
|
||||
RecordType(); // DO NOT IMPLEMENT
|
||||
public:
|
||||
|
||||
RecordDecl *getDecl() const {
|
||||
return reinterpret_cast<RecordDecl*>(TaggedType::getDecl());
|
||||
return reinterpret_cast<RecordDecl*>(TagType::getDecl());
|
||||
}
|
||||
|
||||
static bool classof(const Type *T);
|
||||
|
|
|
@ -480,6 +480,18 @@ DIAG(err_exponent_has_no_digits, ERROR,
|
|||
"exponent has no digits")
|
||||
DIAG(err_hexconstant_requires_exponent, ERROR,
|
||||
"hexadecimal floating constants require an exponent")
|
||||
DIAG(err_typecheck_subscript_value, ERROR,
|
||||
"subscripted value is neither array nor pointer")
|
||||
DIAG(err_typecheck_subscript, ERROR,
|
||||
"array subscript is not an integer")
|
||||
DIAG(err_typecheck_member_reference_structUnion, ERROR,
|
||||
"member reference is neither a structure or union")
|
||||
DIAG(err_typecheck_member_reference_arrow, ERROR,
|
||||
"member reference is not a pointer")
|
||||
DIAG(err_typecheck_incomplete_tag, ERROR,
|
||||
"incomplete definition of struct/union '%s'")
|
||||
DIAG(err_typecheck_internal_error, ERROR,
|
||||
"*internal* typechecking error")
|
||||
|
||||
// Statements.
|
||||
DIAG(err_continue_not_in_loop, ERROR,
|
||||
|
|
Loading…
Reference in New Issue