diff --git a/clang/AST/Sema.h b/clang/AST/Sema.h index dcd2ccab996b..ad604e28aa0d 100644 --- a/clang/AST/Sema.h +++ b/clang/AST/Sema.h @@ -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] }; diff --git a/clang/AST/SemaDecl.cpp b/clang/AST/SemaDecl.cpp index 0e5e65861e69..5803def76d86 100644 --- a/clang/AST/SemaDecl.cpp +++ b/clang/AST/SemaDecl.cpp @@ -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); + } +} diff --git a/clang/AST/SemaExpr.cpp b/clang/AST/SemaExpr.cpp index 715cb414b260..7bc54550f166 100644 --- a/clang/AST/SemaExpr.cpp +++ b/clang/AST/SemaExpr.cpp @@ -188,7 +188,7 @@ ParseSizeOfAlignOfTypeExpr(SourceLocation OpLoc, bool isSizeof, if (isa(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) { +} + diff --git a/clang/AST/Type.cpp b/clang/AST/Type.cpp index 1177b7527a63..30952c84cc1b 100644 --- a/clang/AST/Type.cpp +++ b/clang/AST/Type.cpp @@ -14,7 +14,9 @@ #include "clang/Lex/IdentifierTable.h" #include "clang/AST/Type.h" #include "clang/AST/Decl.h" + #include + 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(getCanonicalType())) + if (const BuiltinType *BT = dyn_cast(CanonicalType)) return BT->getKind() == BuiltinType::Void; return false; } +bool Type::isFunctionType() const { + return isa(CanonicalType) ? true : false; +} + +bool Type::isPointerType() const { + return isa(CanonicalType) ? true : false; +} + +bool Type::isArrayType() const { + return isa(CanonicalType) ? true : false; +} + +bool Type::isStructureType() const { + if (const TaggedType *TT = dyn_cast(CanonicalType)) { + if (TT->getDecl()->getKind() == Decl::Struct) + return true; + } + return false; +} + +bool Type::isUnionType() const { + if (const TaggedType *TT = dyn_cast(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(CanonicalType); + return BT->getKind() >= BuiltinType::Bool && + BT->getKind() <= BuiltinType::ULongLong; + case Tagged: + const TaggedType *TT = static_cast(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(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(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(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(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(this)->getDecl()->isDefinition(); + return !cast(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(this)->getSize() == 0; + return cast(CanonicalType)->getSize() == 0; } } diff --git a/clang/Sema/Sema.h b/clang/Sema/Sema.h index dcd2ccab996b..ad604e28aa0d 100644 --- a/clang/Sema/Sema.h +++ b/clang/Sema/Sema.h @@ -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] }; diff --git a/clang/Sema/SemaDecl.cpp b/clang/Sema/SemaDecl.cpp index 0e5e65861e69..5803def76d86 100644 --- a/clang/Sema/SemaDecl.cpp +++ b/clang/Sema/SemaDecl.cpp @@ -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); + } +} diff --git a/clang/Sema/SemaExpr.cpp b/clang/Sema/SemaExpr.cpp index 715cb414b260..7bc54550f166 100644 --- a/clang/Sema/SemaExpr.cpp +++ b/clang/Sema/SemaExpr.cpp @@ -188,7 +188,7 @@ ParseSizeOfAlignOfTypeExpr(SourceLocation OpLoc, bool isSizeof, if (isa(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) { +} + diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index f609201bfd7e..54dccbfd3e1e 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -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(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; diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 6d0b1277bf92..4cd5653a5893 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -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(can) && "Invalid canonoical type"); + assert(!isa(can) && "Invalid canonical type"); } friend class ASTContext; // ASTContext creates these. public: