This machine mirrors various open-source projects.
20 Gbit/s uplink.
If there are any issues or you want another project mirrored, please contact
mirror-service -=AT=- netcologne DOT de !
00001 //===-- typecheck/RangeChecker.cpp ---------------------------- -*- C++ -*-===// 00002 // 00003 // This file is distributed under the MIT license. See LICENSE.txt for details. 00004 // 00005 // Copyright (C) 2009, Stephen Wilson 00006 // 00007 //===----------------------------------------------------------------------===// 00008 00009 #include "RangeChecker.h" 00010 #include "TypeCheck.h" 00011 #include "comma/ast/Expr.h" 00012 #include "comma/ast/Range.h" 00013 00014 using namespace comma; 00015 00016 using llvm::dyn_cast; 00017 using llvm::cast; 00018 using llvm::isa; 00019 00020 DiagnosticStream &RangeChecker::report(Location loc, diag::Kind kind) 00021 { 00022 AstResource &resource = TC.getAstResource(); 00023 SourceLocation sloc = resource.getTextProvider().getSourceLocation(loc); 00024 return TC.getDiagnostic().report(sloc, kind); 00025 } 00026 00027 bool RangeChecker::checkDeclarationRange(Expr *lower, Expr *upper) 00028 { 00029 // Resolve the lower and upper expressions to be in the integer class of 00030 // types. 00031 if (!TC.checkExprInContext(lower, Type::CLASS_Integer)) 00032 return false; 00033 if (!TC.checkExprInContext(upper, Type::CLASS_Integer)) 00034 return false; 00035 00036 // Ensure both expressions are static. 00037 if (!(TC.ensureStaticIntegerExpr(lower) && 00038 TC.ensureStaticIntegerExpr(upper))) 00039 return false; 00040 00041 return true; 00042 } 00043 00044 DiscreteType *RangeChecker::checkDSTRange(Expr *lower, Expr *upper) 00045 { 00046 // If neither the lower or upper bound expressions have a resolved type, 00047 // evaluate the lower with a discrete class as context, then evaluate the 00048 // upper bound wrt the resolved type. 00049 if (!lower->hasResolvedType() && !upper->hasResolvedType()) { 00050 if (!TC.checkExprInContext(lower, Type::CLASS_Discrete)) 00051 return 0; 00052 if (!(upper = TC.checkExprInContext(upper, lower->getType()))) 00053 return 0; 00054 } 00055 else if (lower->hasResolvedType() && !upper->hasResolvedType()) { 00056 if (!isa<DiscreteType>(lower->getType())) { 00057 report(lower->getLocation(), diag::EXPECTED_DISCRETE_SUBTYPE); 00058 return 0; 00059 } 00060 if (!(upper = TC.checkExprInContext(upper, lower->getType()))) 00061 return 0; 00062 } 00063 else if (upper->hasResolvedType() && !lower->hasResolvedType()) { 00064 if (!isa<DiscreteType>(upper->getType())) { 00065 report(upper->getLocation(), diag::EXPECTED_DISCRETE_SUBTYPE); 00066 return 0; 00067 } 00068 if (!(lower = TC.checkExprInContext(lower, upper->getType()))) 00069 return 0; 00070 } 00071 else { 00072 // Both bounds have a type. Check for compatibility. 00073 if (!isa<DiscreteType>(lower->getType())) { 00074 report(lower->getLocation(), diag::EXPECTED_DISCRETE_SUBTYPE); 00075 return 0; 00076 } 00077 00078 if (!isa<DiscreteType>(upper->getType())) { 00079 report(upper->getLocation(), diag::EXPECTED_DISCRETE_SUBTYPE); 00080 return 0; 00081 } 00082 00083 if (!TC.covers(upper->getType(), lower->getType())) { 00084 report(lower->getLocation(), diag::INCOMPATIBLE_RANGE_TYPES); 00085 return 0; 00086 } 00087 } 00088 00089 DiscreteType *rangeTy = cast<DiscreteType>(lower->getType()); 00090 00091 // If the type of range is root_integer, replace the lower and upper bounds 00092 // with conversion expressions to Integer. 00093 if (rangeTy == TC.getAstResource().getTheRootIntegerType()) { 00094 rangeTy = TC.getAstResource().getTheIntegerType(); 00095 lower = new ConversionExpr(lower, rangeTy, lower->getLocation()); 00096 upper = new ConversionExpr(upper, rangeTy, upper->getLocation()); 00097 } 00098 00099 // Form a constrained discrete subtype constrained by the given bounds. 00100 rangeTy = TC.getAstResource().createDiscreteSubtype(rangeTy, lower, upper); 00101 00102 return rangeTy; 00103 } 00104 00105 DiscreteType *RangeChecker::checkSubtypeRange(DiscreteType *base, 00106 Expr *lower, Expr *upper) 00107 { 00108 if (!(lower = TC.checkExprInContext(lower, base)) || 00109 !(upper = TC.checkExprInContext(upper, base))) 00110 return 0; 00111 00112 return TC.getAstResource().createDiscreteSubtype(base, lower, upper); 00113 } 00114 00115 bool RangeChecker::resolveRange(Range *range, DiscreteType *type) 00116 { 00117 assert(!range->hasType() && "Range already has a resolved type!"); 00118 00119 Expr *lower = range->getLowerBound(); 00120 Expr *upper = range->getUpperBound(); 00121 00122 if (!(lower = TC.checkExprInContext(lower, type)) || 00123 !(upper = TC.checkExprInContext(upper, type))) 00124 return false; 00125 00126 range->setLowerBound(lower); 00127 range->setUpperBound(upper); 00128 range->setType(cast<DiscreteType>(lower->getType())); 00129 return true; 00130 }