AString sp::BuildTypeName(Type *aType, Atom *name, TypeDiagFlags flags) { if (ArrayType *type = aType->asArray()) { Vector<ArrayType *> stack; Type *cursor = type; Type *innermost = nullptr; for (;;) { if (!cursor->isArray()) { innermost = cursor; break; } stack.append(cursor->toArray()); cursor = cursor->toArray()->contained(); } AutoString builder; if (aType->isConst() || !!(flags & TypeDiagFlags::IsConst)) builder = "const "; builder = builder + BuildTypeName(innermost, nullptr, flags & kDiagFlagsInnerMask); bool hasFixedLengths = false; AutoString brackets; for (size_t i = 0; i < stack.length(); i++) { if (!stack[i]->hasFixedLength()) { brackets = brackets + "[]"; continue; } hasFixedLengths = true; brackets = brackets + "[" + AutoString(stack[i]->fixedLength()) + "]"; } if (name) { if (hasFixedLengths) builder = builder + " " + name->chars() + brackets; else builder = builder + brackets + " " + name->chars(); } else { builder = builder + brackets; } return AString(builder.ptr()); } AutoString builder; if (FunctionType *type = aType->asFunction()) builder = BuildTypeFromSignature(type->signature(), flags & kDiagFlagsInnerMask); else builder = GetBaseTypeName(aType); if (!!(flags & TypeDiagFlags::IsByRef)) { builder = builder + "&"; } if (name) builder = builder + " " + name->chars(); return AString(builder.ptr()); }
bool Preprocessor::enterFile(TokenKind directive, const SourceLocation &from, const char *file, const char *where) { if (disable_includes_) return false; AutoString path = searchPaths(file, where); if (!path.length()) { // Try to append '.inc'. size_t len = strlen(file); if (len < 4 || strcmp(&file[len - 4], ".inc") != 0) { AutoString new_file = AutoString(file) + ".inc"; path = searchPaths(new_file, where); } } if (!path.length()) { if (directive == TOK_M_TRYINCLUDE) return true; cc_.report(from, rmsg::include_not_found) << file; return false; } ReportingContext rc(cc_, from); Ref<SourceFile> new_file = cc_.source().open(rc, path.ptr()); if (!new_file) return false; LREntry tl = cc_.source().trackFile(from, new_file); if (!tl.valid()) { // Error was already reported. return false; } if (include_depth_ >= kMaxIncludeDepth) { cc_.report(from, rmsg::include_depth_exceeded); return false; } include_depth_++; assert(!macro_lexer_ && lexer_); lexer_stack_.append(SavedLexer(lexer_, nullptr)); lexer_ = new Lexer(cc_, *this, lexer_->options(), new_file, tl); return true; }
static AString BuildTypeFromSignature(const FunctionSignature *sig, TypeDiagFlags flags) { AutoString base = "function "; base = base + BuildTypeFromTypeExpr(sig->returnType(), nullptr, flags & kDiagFlagsInnerMask); base = base + "("; for (size_t i = 0; i < sig->parameters()->length(); i++) { TypeDiagFlags varFlags = flags & kDiagFlagsInnerMask; Atom *name = !!(flags & TypeDiagFlags::Names) ? sig->parameters()->at(i)->name() : nullptr; if (sig->parameters()->at(i)->sym()->isByRef()) varFlags |= TypeDiagFlags::IsByRef; base = base + BuildTypeFromTypeExpr(sig->parameters()->at(i)->te(), name, varFlags); if (i != sig->parameters()->length() - 1) base = base + ", "; } base = base + ")"; return AString(base.ptr()); }
JsonList *toJson(const ParameterList *params) { JsonList *list = new (pool_) JsonList(); for (size_t i = 0; i < params->length(); i++) { VarDecl *decl = params->at(i); JsonObject *obj = new (pool_) JsonObject(); obj->add(atom_type_, toJson(decl, false)); if (decl->name()) { obj->add(atom_name_, toJson(decl->name())); obj->add(atom_decl_, toJson(decl, true)); } else { obj->add(atom_name_, toJson("...")); AutoString builder = BuildTypeName(decl->te(), nullptr, TypeDiagFlags::Names); builder = builder + " ..."; obj->add(atom_decl_, toJson(builder.ptr())); } list->add(obj); } return list; }
static AString BuildTypeFromSpecifier(const TypeSpecifier *spec, Atom *name, TypeDiagFlags flags) { AutoString base; if (spec->isConst() || !!(flags & TypeDiagFlags::IsConst)) base = "const "; switch (spec->resolver()) { case TOK_LABEL: { // HACK: we should move these atoms into the context. const char *chars = spec->proxy()->name()->chars(); if (strcmp(chars, "Float") == 0) base = base + "float"; else if (strcmp(chars, "String") == 0) base = base + "char"; else if (strcmp(chars, "_") == 0) base = base + "int"; else base = base + chars; break; } case TOK_NAME: base = base + spec->proxy()->name()->chars(); break; case TOK_IMPLICIT_INT: base = base + "int"; break; case TOK_FUNCTION: base = base + BuildTypeFromSignature(spec->signature(), flags & kDiagFlagsInnerMask); break; case TOK_DEFINED: base = base + BuildTypeName(spec->getResolvedBase(), nullptr, flags & kDiagFlagsInnerMask); break; default: base = base + TokenNames[spec->resolver()]; break; } // We need type analysis to determine the true type, so just make a semi- // intelligent guess based on whether or not any rank has a sized dimension. bool postDims = (spec->isNewDecl() && spec->hasPostDims()) || (spec->isOldDecl() && spec->dims()); if (name && postDims) base = base + " " + name->chars(); for (size_t i = 0; i < spec->rank(); i++) { if (Expression *expr = spec->sizeOfRank(i)) { if (IntegerLiteral *lit = expr->asIntegerLiteral()) { char value[24]; SafeSprintf(value, sizeof(value), "%d", (int)lit->value()); base = base + "[" + value + "]"; continue; } } // Hack. We can do better if it becomes necessary, these types are only // for diagnostics. base = base + "[]"; } if (name && !postDims) { base = base + " "; if (spec->isByRef()) base = base + "&"; base = base + name->chars(); } else { if (spec->isByRef()) base = base + "&"; } if (spec->isVariadic()) base = base + " ..."; return AString(base.ptr()); }