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:
Steve Naroff 2007-03-23 22:27:02 +00:00
parent 26c8ea5fab
commit f1e53698a4
17 changed files with 249 additions and 72 deletions

View File

@ -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();
}

View File

@ -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];

View File

@ -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 {

View File

@ -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

View File

@ -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) {
}

View File

@ -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....
}

View File

@ -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;

View File

@ -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

View File

@ -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 ']'.

View File

@ -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 {

View File

@ -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

View File

@ -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) {
}

View File

@ -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.

View File

@ -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; }

View File

@ -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;

View File

@ -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);

View File

@ -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,