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 //===-- CheckAttrib.cpp --------------------------------------- -*- C++ -*-===// 00002 // 00003 // This file is distributed under the MIT license. See LICENSE.txt for details. 00004 // 00005 // Copyright (C) 2009-2010, Stephen Wilson 00006 // 00007 //===----------------------------------------------------------------------===// 00008 00009 #include "TypeCheck.h" 00010 #include "comma/ast/AttribDecl.h" 00011 #include "comma/ast/AttribExpr.h" 00012 #include "comma/ast/RangeAttrib.h" 00013 #include "comma/ast/TypeRef.h" 00014 00015 using namespace comma; 00016 using llvm::dyn_cast_or_null; 00017 using llvm::dyn_cast; 00018 using llvm::cast; 00019 using llvm::isa; 00020 00021 namespace { 00022 00024 class AttributeChecker { 00025 00026 public: 00027 AttributeChecker(TypeCheck &TC, attrib::AttributeID ID) 00028 : TC(TC), 00029 resource(TC.getAstResource()), 00030 diagnostic(TC.getDiagnostic()), 00031 ID(ID) { } 00032 00033 Ast *checkAttribute(Ast *prefix, Location loc); 00034 00035 private: 00036 TypeCheck &TC; 00037 AstResource &resource; 00038 Diagnostic &diagnostic; 00039 attrib::AttributeID ID; 00040 00042 const char *attributeName() { 00043 return attrib::getAttributeString(ID); 00044 } 00045 00056 AttribExpr *checkBound(Ast *prefix, Location loc); 00057 00059 ScalarBoundAE *checkScalarBound(TypeRef *prefix, Location loc); 00060 00062 ArrayBoundAE *checkArrayBound(Expr *prefix, Location loc); 00063 00065 RangeAttrib *checkRange(Ast *prefix, Location loc); 00066 00070 SubroutineRef *checkPosVal(Ast *prefix, Location loc); 00071 00072 SourceLocation getSourceLoc(Location loc) const { 00073 return resource.getTextProvider().getSourceLocation(loc); 00074 } 00075 00076 DiagnosticStream &report(Location loc, diag::Kind kind) { 00077 return diagnostic.report(getSourceLoc(loc), kind); 00078 } 00079 }; 00080 00081 Ast *AttributeChecker::checkAttribute(Ast *prefix, Location loc) 00082 { 00083 Ast *result = 0; 00084 00085 switch (ID) { 00086 default: 00087 assert(false && "Unknown attribute!"); 00088 break; 00089 00090 case attrib::First: 00091 case attrib::Last: 00092 result = checkBound(prefix, loc); 00093 break; 00094 00095 case attrib::Pos: 00096 case attrib::Val: 00097 result = checkPosVal(prefix, loc); 00098 break; 00099 00100 case attrib::Range: 00101 result = checkRange(prefix, loc); 00102 break; 00103 }; 00104 return result; 00105 } 00106 00107 AttribExpr *AttributeChecker::checkBound(Ast *prefix, Location loc) 00108 { 00109 AttribExpr *result = 0; 00110 00111 if (TypeRef *ref = dyn_cast<TypeRef>(prefix)) 00112 result = checkScalarBound(ref, loc); 00113 else if (Expr *expr = dyn_cast<Expr>(prefix)) 00114 result = checkArrayBound(expr, loc); 00115 else { 00116 // FIXME: The location here is of the attribute, not the prefix. The 00117 // AST should provide a service similar to TypeCheck::getNodeLoc. 00118 report(loc, diag::INVALID_ATTRIB_PREFIX) << attributeName(); 00119 } 00120 return result; 00121 } 00122 00123 ScalarBoundAE *AttributeChecker::checkScalarBound(TypeRef *prefix, Location loc) 00124 { 00125 // FIXME: It is possible that the TypeRef is incomplete. We should 00126 // diagnose that fact rather than ignore it. 00127 00128 // When the prefix is a type, it must resolve to a scalar type. 00129 TypeDecl *decl = prefix->getTypeDecl(); 00130 DiscreteType *prefixTy = dyn_cast<DiscreteType>(decl->getType()); 00131 00132 if (!decl) { 00133 report(loc, diag::ATTRIB_OF_NON_SCALAR) << attributeName(); 00134 return 0; 00135 } 00136 00137 if (ID == attrib::First) 00138 return new FirstAE(prefixTy, loc); 00139 else 00140 return new LastAE(prefixTy, loc); 00141 } 00142 00143 ArrayBoundAE *AttributeChecker::checkArrayBound(Expr *prefix, Location loc) 00144 { 00145 ArrayType *arrTy = dyn_cast<ArrayType>(prefix->getType()); 00146 00147 if (!arrTy) { 00148 report(loc, diag::ATTRIB_OF_NON_ARRAY) << attributeName(); 00149 return 0; 00150 } 00151 00152 if (ID == attrib::First) 00153 return new FirstArrayAE(prefix, loc); 00154 else 00155 return new LastArrayAE(prefix, loc); 00156 } 00157 00158 RangeAttrib *AttributeChecker::checkRange(Ast *prefix, Location loc) 00159 { 00160 // If the prefix denotes an expression it must resolve to an array type 00161 // including any implicit dereferencing. 00162 if (Expr *expr = dyn_cast<Expr>(prefix)) { 00163 if (!(expr->hasResolvedType() || 00164 TC.checkExprInContext(expr, Type::CLASS_Array))) 00165 return 0; 00166 00167 if (!isa<ArrayType>(expr->getType())) { 00168 Type *type = expr->getType(); 00169 if ((type = TC.getCoveringDereference(type, Type::CLASS_Array))) 00170 expr = TC.implicitlyDereference(expr, type); 00171 else { 00172 report(loc, diag::ATTRIB_OF_NON_ARRAY) << attributeName(); 00173 return 0; 00174 } 00175 } 00176 return new ArrayRangeAttrib(expr, loc); 00177 } 00178 00179 // Otherwise, the prefix must be a TypeRef resolving to a scalar type. 00180 TypeRef *ref = dyn_cast<TypeRef>(prefix); 00181 00182 if (!ref || !ref->referencesTypeDecl()) { 00183 report(loc, diag::INVALID_ATTRIB_PREFIX) << attributeName(); 00184 return 0; 00185 } 00186 00187 TypeDecl *tyDecl = ref->getTypeDecl(); 00188 DiscreteType *prefixTy = dyn_cast<DiscreteType>(tyDecl->getType()); 00189 00190 if (!prefixTy) { 00191 report(loc, diag::INVALID_ATTRIB_PREFIX) << attributeName(); 00192 return 0; 00193 } 00194 00195 return new ScalarRangeAttrib(prefixTy, loc); 00196 } 00197 00198 SubroutineRef *AttributeChecker::checkPosVal(Ast *prefix, Location loc) 00199 { 00200 assert((ID == attrib::Pos || ID == attrib::Val) && 00201 "Unexpected attribute ID!"); 00202 00203 TypeRef *ref = dyn_cast<TypeRef>(prefix); 00204 00205 if (!(ref && ref->referencesTypeDecl())) { 00206 report(prefix->getLocation(), diag::EXPECTED_DISCRETE_SUBTYPE); 00207 return 0; 00208 } 00209 00210 TypeDecl *tyDecl = ref->getTypeDecl(); 00211 FunctionAttribDecl *attrib; 00212 00213 if (IntegerDecl *intDecl = dyn_cast<IntegerDecl>(tyDecl)) 00214 attrib = intDecl->getAttribute(ID); 00215 else if (EnumerationDecl *enumDecl = dyn_cast<EnumerationDecl>(tyDecl)) 00216 attrib = enumDecl->getAttribute(ID); 00217 00218 if (!attrib) { 00219 report(prefix->getLocation(), diag::EXPECTED_DISCRETE_SUBTYPE); 00220 return 0; 00221 } 00222 00223 return new SubroutineRef(loc, attrib); 00224 } 00225 00226 } // end anonymous namespace. 00227 00228 00229 Ast *TypeCheck::checkAttribute(attrib::AttributeID ID, 00230 Ast *prefix, Location loc) 00231 { 00232 AttributeChecker AC(*this, ID); 00233 return AC.checkAttribute(prefix, loc); 00234 }