From: Chris Lattner Date: Sat, 12 Jul 2008 00:38:25 +0000 (+0000) Subject: Add support for __builtin_type_compatible_p, enums, etc. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4c4867e140327fa3b56306fa03c64c8e6a7c95ef;p=clang Add support for __builtin_type_compatible_p, enums, etc. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@53500 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index caf22311ad..78e0470b68 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -226,8 +226,25 @@ public: bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); } + bool VisitIntegerLiteral(const IntegerLiteral *E) { + Result = E->getValue(); + Result.setIsUnsigned(E->getType()->isUnsignedIntegerType()); + return true; + } + bool VisitCharacterLiteral(const CharacterLiteral *E) { + Result.zextOrTrunc(getIntTypeSizeInBits(E->getType())); + Result = E->getValue(); + Result.setIsUnsigned(E->getType()->isUnsignedIntegerType()); + return true; + } + bool VisitTypesCompatibleExpr(const TypesCompatibleExpr *E) { + Result.zextOrTrunc(getIntTypeSizeInBits(E->getType())); + Result = Info.Ctx.typesAreCompatible(E->getArgType1(), E->getArgType2()); + return true; + } + bool VisitDeclRefExpr(const DeclRefExpr *E); + bool VisitCallExpr(const CallExpr *E); bool VisitBinaryOperator(const BinaryOperator *E); - bool VisitUnaryOperator(const UnaryOperator *E); bool VisitCastExpr(const CastExpr* E) { @@ -240,18 +257,7 @@ public: return EvaluateSizeAlignOf(E->isSizeOf(), E->getArgumentType(), E->getType()); } - - bool VisitIntegerLiteral(const IntegerLiteral *E) { - Result = E->getValue(); - Result.setIsUnsigned(E->getType()->isUnsignedIntegerType()); - return true; - } - bool VisitCharacterLiteral(const CharacterLiteral *E) { - Result.zextOrTrunc(getIntTypeSizeInBits(E->getType())); - Result = E->getValue(); - Result.setIsUnsigned(E->getType()->isUnsignedIntegerType()); - return true; - } + private: bool HandleCast(const Expr* SubExpr, QualType DestType); bool EvaluateSizeAlignOf(bool isSizeOf, QualType SrcTy, QualType DstTy); @@ -262,6 +268,26 @@ static bool EvaluateInteger(const Expr* E, APSInt &Result, EvalInfo &Info) { return IntExprEvaluator(Info, Result).Visit(const_cast(E)); } +bool IntExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) { + // Enums are integer constant exprs. + if (const EnumConstantDecl *D = dyn_cast(E->getDecl())) { + Result = D->getInitVal(); + return true; + } + + // Otherwise, random variable references are not constants. + return Error(E->getLocStart(), diag::err_expr_not_constant); +} + + +bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { + Result.zextOrTrunc(getIntTypeSizeInBits(E->getType())); + // __builtin_type_compatible_p is a constant. + if (E->isBuiltinClassifyType(Result)) + return true; + + return Error(E->getLocStart(), diag::err_expr_not_constant); +} bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { // The LHS of a constant expr is always evaluated and needed. @@ -395,7 +421,10 @@ bool IntExprEvaluator::EvaluateSizeAlignOf(bool isSizeOf, QualType SrcTy, } bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { + // Special case unary operators that do not need their subexpression + // evaluated. offsetof/sizeof/alignof are all special. if (E->isOffsetOfOp()) { + Result.zextOrTrunc(getIntTypeSizeInBits(E->getType())); Result = E->evaluateOffsetOf(Info.Ctx); Result.setIsUnsigned(E->getType()->isUnsignedIntegerType()); return true; @@ -410,10 +439,10 @@ bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { return false; switch (E->getOpcode()) { + default: // Address, indirect, pre/post inc/dec, etc are not valid constant exprs. // See C99 6.6p3. - default: - return false; + return Error(E->getOperatorLoc(), diag::err_expr_not_constant); case UnaryOperator::LNot: { bool Val = Result == 0; Result.zextOrTrunc(getIntTypeSizeInBits(E->getType())); @@ -421,8 +450,10 @@ bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { break; } case UnaryOperator::Extension: + // FIXME: Should extension allow i-c-e extension expressions in its scope? + // If so, we could clear the diagnostic ID. case UnaryOperator::Plus: - // The result is always just the subexpr + // The result is always just the subexpr. break; case UnaryOperator::Minus: Result = -Result;