Bug #:
Submitted by: Reviewed by: Implement type checking. First round of changes are: - Added predicates to Type. - Added predicates to BinExpr. - Added Check hooks that model the categories for Binary ops. - Added TypeRef to Expr. Will lazily eval subclasses... - Misc bug fixes/cleanups. llvm-svn: 39360
This commit is contained in:
parent
bb73acd560
commit
26c8ea5fab
|
@ -24,6 +24,7 @@ namespace clang {
|
|||
class ASTContext;
|
||||
class Preprocessor;
|
||||
class Decl;
|
||||
class Expr;
|
||||
class VarDecl;
|
||||
class TypedefDecl;
|
||||
class FunctionDecl;
|
||||
|
@ -65,7 +66,7 @@ public:
|
|||
virtual TypeResult ParseTypeName(Scope *S, Declarator &D);
|
||||
|
||||
virtual TypeResult ParseParamDeclaratorType(Scope *S, Declarator &D);
|
||||
|
||||
private:
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Symbol table / Decl tracking callbacks: SemaDecl.cpp.
|
||||
//
|
||||
|
@ -98,6 +99,9 @@ private:
|
|||
TypedefDecl *MergeTypeDefDecl(TypedefDecl *New, Decl *Old);
|
||||
FunctionDecl *MergeFunctionDecl(FunctionDecl *New, Decl *Old);
|
||||
VarDecl *MergeVarDecl(VarDecl *New, Decl *Old);
|
||||
/// AddTopLevelDecl - called after the decl has been fully processed.
|
||||
/// Allows for bookkeeping and post-processing of each declaration.
|
||||
void AddTopLevelDecl(Decl *current, Decl *last);
|
||||
|
||||
/// More parsing and symbol table subroutines...
|
||||
VarDecl *ParseParamDeclarator(DeclaratorChunk &FI, unsigned ArgNo,
|
||||
|
@ -215,6 +219,15 @@ public:
|
|||
/// ParseCXXBoolLiteral - Parse {true,false} literals.
|
||||
virtual ExprResult ParseCXXBoolLiteral(SourceLocation OpLoc,
|
||||
tok::TokenKind Kind);
|
||||
private:
|
||||
/// 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
|
||||
void CheckShiftOperands(Expr *op1, Expr *op2); // C99 6.5.7
|
||||
void CheckRelationalOperands(Expr *op1, Expr *op2); // C99 6.5.8
|
||||
void CheckEqualityOperands(Expr *op1, Expr *op2); // C99 6.5.9
|
||||
void CheckBitwiseOperands(Expr *op1, Expr *op2); // C99 6.5.[10...12]
|
||||
void CheckLogicalOperands(Expr *op1, Expr *op2); // C99 6.5.[13,14]
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -288,10 +288,8 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init,
|
|||
S->AddDecl(New);
|
||||
}
|
||||
|
||||
// If this is a top-level decl that is chained to some other (e.g. int A,B,C;)
|
||||
// remember this in the LastInGroupList list.
|
||||
if (LastInGroup && S->getParent() == 0)
|
||||
LastInGroupList.push_back((Decl*)LastInGroup);
|
||||
if (S->getParent() == 0)
|
||||
AddTopLevelDecl(New, (Decl *)LastInGroup);
|
||||
|
||||
return New;
|
||||
}
|
||||
|
@ -714,3 +712,12 @@ void Sema::ParseEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX,
|
|||
Enum->defineElements(&Values[0], Values.size());
|
||||
}
|
||||
|
||||
void Sema::AddTopLevelDecl(Decl *current, Decl *last) {
|
||||
if (!current) return;
|
||||
|
||||
// If this is a top-level decl that is chained to some other (e.g. int A,B,C;)
|
||||
// remember this in the LastInGroupList list.
|
||||
if (last) {
|
||||
LastInGroupList.push_back((Decl*)last);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -188,7 +188,7 @@ ParseSizeOfAlignOfTypeExpr(SourceLocation OpLoc, bool isSizeof,
|
|||
if (isa<FunctionType>(ArgTy) && isSizeof) {
|
||||
// alignof(function) is allowed.
|
||||
Diag(OpLoc, diag::ext_sizeof_function_type);
|
||||
return new IntegerLiteral(/*1*/);
|
||||
return new IntegerLiteral(1, Context.IntTy);
|
||||
} else if (ArgTy->isVoidType()) {
|
||||
Diag(OpLoc, diag::ext_sizeof_void_type, isSizeof ? "sizeof" : "__alignof");
|
||||
} else if (ArgTy->isIncompleteType()) {
|
||||
|
@ -196,7 +196,7 @@ ParseSizeOfAlignOfTypeExpr(SourceLocation OpLoc, bool isSizeof,
|
|||
ArgTy->getAsString(TypeName);
|
||||
Diag(OpLoc, isSizeof ? diag::err_sizeof_incomplete_type :
|
||||
diag::err_alignof_incomplete_type, TypeName);
|
||||
return new IntegerLiteral(/*0*/);
|
||||
return new IntegerLiteral(0, Context.IntTy);
|
||||
}
|
||||
|
||||
return new SizeOfAlignOfTypeExpr(isSizeof, ArgTy);
|
||||
|
@ -289,6 +289,21 @@ Action::ExprResult Sema::ParseBinOp(SourceLocation TokLoc, tok::TokenKind Kind,
|
|||
case tok::comma: Opc = BinaryOperator::Comma; break;
|
||||
}
|
||||
|
||||
if (BinaryOperator::isMultiplicativeOp(Opc))
|
||||
CheckMultiplicativeOperands((Expr*)LHS, (Expr*)RHS);
|
||||
else if (BinaryOperator::isAdditiveOp(Opc))
|
||||
CheckAdditiveOperands((Expr*)LHS, (Expr*)RHS);
|
||||
else if (BinaryOperator::isShiftOp(Opc))
|
||||
CheckShiftOperands((Expr*)LHS, (Expr*)RHS);
|
||||
else if (BinaryOperator::isRelationalOp(Opc))
|
||||
CheckRelationalOperands((Expr*)LHS, (Expr*)RHS);
|
||||
else if (BinaryOperator::isEqualityOp(Opc))
|
||||
CheckEqualityOperands((Expr*)LHS, (Expr*)RHS);
|
||||
else if (BinaryOperator::isBitwiseOp(Opc))
|
||||
CheckBitwiseOperands((Expr*)LHS, (Expr*)RHS);
|
||||
else if (BinaryOperator::isLogicalOp(Opc))
|
||||
CheckLogicalOperands((Expr*)LHS, (Expr*)RHS);
|
||||
|
||||
return new BinaryOperator((Expr*)LHS, (Expr*)RHS, Opc);
|
||||
}
|
||||
|
||||
|
@ -301,3 +316,24 @@ Action::ExprResult Sema::ParseConditionalOp(SourceLocation QuestionLoc,
|
|||
return new ConditionalOperator((Expr*)Cond, (Expr*)LHS, (Expr*)RHS);
|
||||
}
|
||||
|
||||
void Sema::CheckMultiplicativeOperands(Expr *op1, Expr *op2) {
|
||||
}
|
||||
|
||||
void Sema::CheckAdditiveOperands(Expr *op1, Expr *op2) {
|
||||
}
|
||||
|
||||
void Sema::CheckShiftOperands(Expr *op1, Expr *op2) {
|
||||
}
|
||||
|
||||
void Sema::CheckRelationalOperands(Expr *op1, Expr *op2) {
|
||||
}
|
||||
|
||||
void Sema::CheckEqualityOperands(Expr *op1, Expr *op2) {
|
||||
}
|
||||
|
||||
void Sema::CheckBitwiseOperands(Expr *op1, Expr *op2) {
|
||||
}
|
||||
|
||||
void Sema::CheckLogicalOperands(Expr *op1, Expr *op2) {
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,9 @@
|
|||
#include "clang/Lex/IdentifierTable.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace clang;
|
||||
|
||||
|
@ -22,16 +24,105 @@ Type::~Type() {}
|
|||
|
||||
/// isVoidType - Helper method to determine if this is the 'void' type.
|
||||
bool Type::isVoidType() const {
|
||||
if (const BuiltinType *BT = dyn_cast<BuiltinType>(getCanonicalType()))
|
||||
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
|
||||
return BT->getKind() == BuiltinType::Void;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Type::isFunctionType() const {
|
||||
return isa<FunctionType>(CanonicalType) ? true : false;
|
||||
}
|
||||
|
||||
bool Type::isPointerType() const {
|
||||
return isa<PointerType>(CanonicalType) ? true : false;
|
||||
}
|
||||
|
||||
bool Type::isArrayType() const {
|
||||
return isa<ArrayType>(CanonicalType) ? true : false;
|
||||
}
|
||||
|
||||
bool Type::isStructureType() const {
|
||||
if (const TaggedType *TT = dyn_cast<TaggedType>(CanonicalType)) {
|
||||
if (TT->getDecl()->getKind() == Decl::Struct)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Type::isUnionType() const {
|
||||
if (const TaggedType *TT = dyn_cast<TaggedType>(CanonicalType)) {
|
||||
if (TT->getDecl()->getKind() == Decl::Union)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Type::isIntegralType() const {
|
||||
switch (CanonicalType->getTypeClass()) {
|
||||
default: return false;
|
||||
case Builtin:
|
||||
const BuiltinType *BT = static_cast<BuiltinType*>(CanonicalType);
|
||||
return BT->getKind() >= BuiltinType::Bool &&
|
||||
BT->getKind() <= BuiltinType::ULongLong;
|
||||
case Tagged:
|
||||
const TaggedType *TT = static_cast<TaggedType*>(CanonicalType);
|
||||
if (TT->getDecl()->getKind() == Decl::Enum)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Type::isFloatingType() const {
|
||||
switch (CanonicalType->getTypeClass()) {
|
||||
default: return false;
|
||||
case Builtin:
|
||||
const BuiltinType *BT = static_cast<BuiltinType*>(CanonicalType);
|
||||
return BT->getKind() >= BuiltinType::Float &&
|
||||
BT->getKind() <= BuiltinType::LongDoubleComplex;
|
||||
}
|
||||
}
|
||||
|
||||
bool Type::isArithmeticType() const {
|
||||
switch (CanonicalType->getTypeClass()) {
|
||||
default: return false;
|
||||
case Builtin:
|
||||
const BuiltinType *BT = static_cast<BuiltinType*>(CanonicalType);
|
||||
return BT->getKind() >= BuiltinType::Bool &&
|
||||
BT->getKind() <= BuiltinType::LongDoubleComplex;
|
||||
}
|
||||
}
|
||||
|
||||
bool Type::isScalarType() const {
|
||||
switch (CanonicalType->getTypeClass()) {
|
||||
default: return false;
|
||||
case Builtin:
|
||||
const BuiltinType *BT = static_cast<BuiltinType*>(CanonicalType);
|
||||
return BT->getKind() >= BuiltinType::Bool &&
|
||||
BT->getKind() <= BuiltinType::LongDoubleComplex;
|
||||
case Pointer:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool Type::isAggregateType() const {
|
||||
switch (CanonicalType->getTypeClass()) {
|
||||
default: return false;
|
||||
case Array:
|
||||
return true;
|
||||
case Tagged:
|
||||
const TaggedType *TT = static_cast<TaggedType*>(CanonicalType);
|
||||
if (TT->getDecl()->getKind() == Decl::Struct)
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// isIncompleteType - Return true if this is an incomplete type (C99 6.2.5p1)
|
||||
/// - a type that can describe objects, but which lacks information needed to
|
||||
/// determine its size.
|
||||
bool Type::isIncompleteType() const {
|
||||
switch (getTypeClass()) {
|
||||
bool Type::isIncompleteType() const {
|
||||
switch (CanonicalType->getTypeClass()) {
|
||||
default: return false;
|
||||
case Builtin:
|
||||
// Void is the only incomplete builtin type. Per C99 6.2.5p19, it can never
|
||||
|
@ -40,17 +131,10 @@ 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>(this)->getDecl()->isDefinition();
|
||||
return !cast<TaggedType>(CanonicalType)->getDecl()->isDefinition();
|
||||
case Array:
|
||||
// An array of unknown size is an incomplete type (C99 6.2.5p22).
|
||||
// In C99, an unknown size is permitted in 4 instances:
|
||||
// - The array being declared is a formal parameter of a function.
|
||||
// - The declarator is accompanied by an initializer from which the array
|
||||
// can be deduced (char foo[] = "whatever").
|
||||
// - Forward declarations (extern int matrix[][7]).
|
||||
// - The last component of a structure (flexible array idiom).
|
||||
// Clients of this routine will need to determine if the size is required.
|
||||
return cast<ArrayType>(this)->getSize() == 0;
|
||||
return cast<ArrayType>(CanonicalType)->getSize() == 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace clang {
|
|||
class ASTContext;
|
||||
class Preprocessor;
|
||||
class Decl;
|
||||
class Expr;
|
||||
class VarDecl;
|
||||
class TypedefDecl;
|
||||
class FunctionDecl;
|
||||
|
@ -65,7 +66,7 @@ public:
|
|||
virtual TypeResult ParseTypeName(Scope *S, Declarator &D);
|
||||
|
||||
virtual TypeResult ParseParamDeclaratorType(Scope *S, Declarator &D);
|
||||
|
||||
private:
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Symbol table / Decl tracking callbacks: SemaDecl.cpp.
|
||||
//
|
||||
|
@ -98,6 +99,9 @@ private:
|
|||
TypedefDecl *MergeTypeDefDecl(TypedefDecl *New, Decl *Old);
|
||||
FunctionDecl *MergeFunctionDecl(FunctionDecl *New, Decl *Old);
|
||||
VarDecl *MergeVarDecl(VarDecl *New, Decl *Old);
|
||||
/// AddTopLevelDecl - called after the decl has been fully processed.
|
||||
/// Allows for bookkeeping and post-processing of each declaration.
|
||||
void AddTopLevelDecl(Decl *current, Decl *last);
|
||||
|
||||
/// More parsing and symbol table subroutines...
|
||||
VarDecl *ParseParamDeclarator(DeclaratorChunk &FI, unsigned ArgNo,
|
||||
|
@ -215,6 +219,15 @@ public:
|
|||
/// ParseCXXBoolLiteral - Parse {true,false} literals.
|
||||
virtual ExprResult ParseCXXBoolLiteral(SourceLocation OpLoc,
|
||||
tok::TokenKind Kind);
|
||||
private:
|
||||
/// 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
|
||||
void CheckShiftOperands(Expr *op1, Expr *op2); // C99 6.5.7
|
||||
void CheckRelationalOperands(Expr *op1, Expr *op2); // C99 6.5.8
|
||||
void CheckEqualityOperands(Expr *op1, Expr *op2); // C99 6.5.9
|
||||
void CheckBitwiseOperands(Expr *op1, Expr *op2); // C99 6.5.[10...12]
|
||||
void CheckLogicalOperands(Expr *op1, Expr *op2); // C99 6.5.[13,14]
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -288,10 +288,8 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init,
|
|||
S->AddDecl(New);
|
||||
}
|
||||
|
||||
// If this is a top-level decl that is chained to some other (e.g. int A,B,C;)
|
||||
// remember this in the LastInGroupList list.
|
||||
if (LastInGroup && S->getParent() == 0)
|
||||
LastInGroupList.push_back((Decl*)LastInGroup);
|
||||
if (S->getParent() == 0)
|
||||
AddTopLevelDecl(New, (Decl *)LastInGroup);
|
||||
|
||||
return New;
|
||||
}
|
||||
|
@ -714,3 +712,12 @@ void Sema::ParseEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX,
|
|||
Enum->defineElements(&Values[0], Values.size());
|
||||
}
|
||||
|
||||
void Sema::AddTopLevelDecl(Decl *current, Decl *last) {
|
||||
if (!current) return;
|
||||
|
||||
// If this is a top-level decl that is chained to some other (e.g. int A,B,C;)
|
||||
// remember this in the LastInGroupList list.
|
||||
if (last) {
|
||||
LastInGroupList.push_back((Decl*)last);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -188,7 +188,7 @@ ParseSizeOfAlignOfTypeExpr(SourceLocation OpLoc, bool isSizeof,
|
|||
if (isa<FunctionType>(ArgTy) && isSizeof) {
|
||||
// alignof(function) is allowed.
|
||||
Diag(OpLoc, diag::ext_sizeof_function_type);
|
||||
return new IntegerLiteral(/*1*/);
|
||||
return new IntegerLiteral(1, Context.IntTy);
|
||||
} else if (ArgTy->isVoidType()) {
|
||||
Diag(OpLoc, diag::ext_sizeof_void_type, isSizeof ? "sizeof" : "__alignof");
|
||||
} else if (ArgTy->isIncompleteType()) {
|
||||
|
@ -196,7 +196,7 @@ ParseSizeOfAlignOfTypeExpr(SourceLocation OpLoc, bool isSizeof,
|
|||
ArgTy->getAsString(TypeName);
|
||||
Diag(OpLoc, isSizeof ? diag::err_sizeof_incomplete_type :
|
||||
diag::err_alignof_incomplete_type, TypeName);
|
||||
return new IntegerLiteral(/*0*/);
|
||||
return new IntegerLiteral(0, Context.IntTy);
|
||||
}
|
||||
|
||||
return new SizeOfAlignOfTypeExpr(isSizeof, ArgTy);
|
||||
|
@ -289,6 +289,21 @@ Action::ExprResult Sema::ParseBinOp(SourceLocation TokLoc, tok::TokenKind Kind,
|
|||
case tok::comma: Opc = BinaryOperator::Comma; break;
|
||||
}
|
||||
|
||||
if (BinaryOperator::isMultiplicativeOp(Opc))
|
||||
CheckMultiplicativeOperands((Expr*)LHS, (Expr*)RHS);
|
||||
else if (BinaryOperator::isAdditiveOp(Opc))
|
||||
CheckAdditiveOperands((Expr*)LHS, (Expr*)RHS);
|
||||
else if (BinaryOperator::isShiftOp(Opc))
|
||||
CheckShiftOperands((Expr*)LHS, (Expr*)RHS);
|
||||
else if (BinaryOperator::isRelationalOp(Opc))
|
||||
CheckRelationalOperands((Expr*)LHS, (Expr*)RHS);
|
||||
else if (BinaryOperator::isEqualityOp(Opc))
|
||||
CheckEqualityOperands((Expr*)LHS, (Expr*)RHS);
|
||||
else if (BinaryOperator::isBitwiseOp(Opc))
|
||||
CheckBitwiseOperands((Expr*)LHS, (Expr*)RHS);
|
||||
else if (BinaryOperator::isLogicalOp(Opc))
|
||||
CheckLogicalOperands((Expr*)LHS, (Expr*)RHS);
|
||||
|
||||
return new BinaryOperator((Expr*)LHS, (Expr*)RHS, Opc);
|
||||
}
|
||||
|
||||
|
@ -301,3 +316,24 @@ Action::ExprResult Sema::ParseConditionalOp(SourceLocation QuestionLoc,
|
|||
return new ConditionalOperator((Expr*)Cond, (Expr*)LHS, (Expr*)RHS);
|
||||
}
|
||||
|
||||
void Sema::CheckMultiplicativeOperands(Expr *op1, Expr *op2) {
|
||||
}
|
||||
|
||||
void Sema::CheckAdditiveOperands(Expr *op1, Expr *op2) {
|
||||
}
|
||||
|
||||
void Sema::CheckShiftOperands(Expr *op1, Expr *op2) {
|
||||
}
|
||||
|
||||
void Sema::CheckRelationalOperands(Expr *op1, Expr *op2) {
|
||||
}
|
||||
|
||||
void Sema::CheckEqualityOperands(Expr *op1, Expr *op2) {
|
||||
}
|
||||
|
||||
void Sema::CheckBitwiseOperands(Expr *op1, Expr *op2) {
|
||||
}
|
||||
|
||||
void Sema::CheckLogicalOperands(Expr *op1, Expr *op2) {
|
||||
}
|
||||
|
||||
|
|
|
@ -27,9 +27,9 @@ namespace clang {
|
|||
/// is required.
|
||||
///
|
||||
class Expr : public Stmt {
|
||||
/// TODO: Type.
|
||||
TypeRef Type;
|
||||
public:
|
||||
Expr(StmtClass SC) : Stmt(SC) {}
|
||||
Expr(StmtClass SC, TypeRef T=0) : Stmt(SC), Type(T) {}
|
||||
~Expr() {}
|
||||
|
||||
virtual void visit(StmtVisitor &Visitor);
|
||||
|
@ -60,25 +60,14 @@ public:
|
|||
static bool classof(const DeclRefExpr *) { return true; }
|
||||
};
|
||||
|
||||
|
||||
// FIXME: The "type" will eventually be moved to Stmt.
|
||||
class IntegerLiteral : public Expr {
|
||||
TypeRef Type; // IntTy, LongTy, LongLongTy
|
||||
// UnsignedIntTy, UnsignedLongTy, UnsignedLongLongTy
|
||||
intmax_t Value;
|
||||
public:
|
||||
// FIXME: To satisfy some of the current adhoc usage...
|
||||
IntegerLiteral() : Expr(IntegerLiteralClass),
|
||||
Type(0), Value(0) {
|
||||
}
|
||||
// type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy,
|
||||
// or UnsignedLongLongTy
|
||||
IntegerLiteral(intmax_t value, TypeRef type)
|
||||
: Expr(IntegerLiteralClass), Type(type), Value(value) {
|
||||
#if 0
|
||||
std::cout << "Value=" << Value;
|
||||
std::cout << " Type= ";
|
||||
std::cout << static_cast<BuiltinType *>(type.getTypePtr())->getName();
|
||||
std::cout << "\n";
|
||||
#endif
|
||||
: Expr(IntegerLiteralClass, type), Value(value) {
|
||||
assert(type->isIntegralType() && "Illegal type in IntegerLiteral");
|
||||
}
|
||||
virtual void visit(StmtVisitor &Visitor);
|
||||
static bool classof(const Stmt *T) {
|
||||
|
@ -89,7 +78,7 @@ public:
|
|||
|
||||
class FloatingLiteral : public Expr {
|
||||
public:
|
||||
FloatingLiteral() : Expr(FloatingLiteralClass) {}
|
||||
FloatingLiteral() : Expr(FloatingLiteralClass) {}
|
||||
virtual void visit(StmtVisitor &Visitor);
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == FloatingLiteralClass;
|
||||
|
@ -328,6 +317,15 @@ public:
|
|||
/// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
|
||||
/// corresponds to, e.g. "<<=".
|
||||
static const char *getOpcodeStr(Opcode Op);
|
||||
|
||||
/// predicates to categorize the respective opcodes.
|
||||
static bool isMultiplicativeOp(Opcode Op) { return Op >= Mul && Op <= Rem; }
|
||||
static bool isAdditiveOp(Opcode Op) { return Op == Add || Op == Sub; }
|
||||
static bool isShiftOp(Opcode Op) { return Op == Shl || Op == Shr; }
|
||||
static bool isRelationalOp(Opcode Op) { return Op >= LT && Op <= GE; }
|
||||
static bool isEqualityOp(Opcode Op) { return Op == EQ || Op == NE; }
|
||||
static bool isBitwiseOp(Opcode Op) { return Op >= And && Op <= Or; }
|
||||
static bool isLogicalOp(Opcode Op) { return Op == LAnd || Op == LOr; }
|
||||
|
||||
Opcode getOpcode() const { return Opc; }
|
||||
Expr *getLHS() { return LHS; }
|
||||
|
@ -338,7 +336,6 @@ public:
|
|||
return T->getStmtClass() == BinaryOperatorClass;
|
||||
}
|
||||
static bool classof(const BinaryOperator *) { return true; }
|
||||
|
||||
private:
|
||||
Expr *LHS, *RHS;
|
||||
Opcode Opc;
|
||||
|
|
|
@ -182,13 +182,26 @@ public:
|
|||
|
||||
bool isCanonical() const { return CanonicalType == this; }
|
||||
Type *getCanonicalType() const { return CanonicalType; }
|
||||
|
||||
/// Helper methods to distinguish type categories. All type predicates
|
||||
/// operate on the canonical type, ignoring typedefs.
|
||||
bool isIntegralType() const; // short/int/long, char, bool, enum { ... }
|
||||
bool isFloatingType() const; // float, double, long double, complex
|
||||
bool isArithmeticType() const; // integral + floating
|
||||
bool isScalarType() const; // arithmetic + pointers
|
||||
bool isAggregateType() const; // arrays, structures
|
||||
|
||||
/// isVoidType - Helper method to determine if this is the 'void' type.
|
||||
bool isVoidType() const;
|
||||
bool isVoidType() const;
|
||||
bool isFunctionType() const;
|
||||
bool isPointerType() const;
|
||||
bool isArrayType() const;
|
||||
bool isStructureType() const;
|
||||
bool isUnionType() const;
|
||||
|
||||
/// isIncompleteType - Return true if this is an incomplete type (C99 6.2.5p1)
|
||||
/// - a type that can describe objects, but which lacks information needed to
|
||||
/// determine its size (e.g. void, or a fwd declared struct).
|
||||
/// determine its size (e.g. void, or a fwd declared struct). Clients of this
|
||||
/// routine will need to determine if the size is actually required.
|
||||
bool isIncompleteType() const;
|
||||
|
||||
virtual void getAsString(std::string &InnerString) const = 0;
|
||||
|
@ -397,7 +410,7 @@ public:
|
|||
class TypedefType : public Type {
|
||||
TypedefDecl *Decl;
|
||||
TypedefType(TypedefDecl *D, Type *can) : Type(TypeName, can), Decl(D) {
|
||||
assert(!isa<TypedefType>(can) && "Invalid canonoical type");
|
||||
assert(!isa<TypedefType>(can) && "Invalid canonical type");
|
||||
}
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
public:
|
||||
|
|
Loading…
Reference in New Issue