// lookupset.cc // code for lookupset.h #include "lookupset.h" // this module #include "variable.h" // Variable, sameEntity #include "template.h" // TemplateInfo #include "cc_flags.h" // bitmapString char const * const lookupFlagNames[NUM_LOOKUPFLAGS] = { "LF_INNER_ONLY", "LF_ONLY_TYPES", "LF_TYPENAME", "LF_SKIP_CLASSES", "LF_ONLY_NAMESPACES", "LF_TYPES_NAMESPACES", "LF_QUALIFIED", "LF_TEMPL_PRIMARY", "LF_FUNCTION_NAME", "LF_DECLARATOR", "LF_SELFNAME", "LF_unused_value2", "LF_TEMPL_PARAM", "LF_SUPPRESS_ERROR", "LF_SUPPRESS_NONEXIST", "LF_IGNORE_USING", "LF_NO_IMPL_THIS", "LF_unused_value3", "LF_QUERY_TAGS", "LF_unused_value", "LF_EXPECTING_TYPE", "LF_EXPLICIT_INST", "LF_ARG_DEP", "LF_GET_SCOPE_ONLY", }; string toString(LookupFlags f) { // make sure I haven't added a flag without adding a string for it xassert(declFlagNames[NUM_LOOKUPFLAGS-1] != NULL); return bitmapString(f, lookupFlagNames, NUM_LOOKUPFLAGS); } // this exists in case gdb's overload resolution is broken (?) string toString_LF(LookupFlags f) { return toString(f); } // vfilter: variable filter // implements variable-filtering aspect of the flags; the idea // is you never query 'variables' without wrapping the call // in a filter Variable *vfilter(Variable *v, LookupFlags flags) { if (!v) return v; if ((flags & LF_ONLY_TYPES) && !v->hasFlag(DF_TYPEDEF)) { return NULL; } if ((flags & LF_ONLY_NAMESPACES) && !v->hasFlag(DF_NAMESPACE)) { return NULL; } if ((flags & LF_TYPES_NAMESPACES) && !v->hasFlag(DF_TYPEDEF) && !v->hasFlag(DF_NAMESPACE)) { return NULL; } if (!(flags & LF_SELFNAME) && v->hasFlag(DF_SELFNAME)) { // the selfname is not visible b/c LF_SELFNAME not specified return NULL; } if ((flags & LF_TEMPL_PARAM) && !v->isTemplateParam()) { return NULL; } return v; } // --------------------- LookupSet ---------------------- LookupSet::LookupSet() {} LookupSet::~LookupSet() {} LookupSet::LookupSet(LookupSet const &obj) { copy(obj); } LookupSet& LookupSet::operator= (LookupSet const &obj) { if (this != &obj) { copy(obj); } return *this; } void LookupSet::copy(LookupSet const &obj) { removeAll(); SObjList::operator=(obj); } Variable *LookupSet::filter(Variable *v, LookupFlags flags) { v = vfilter(v, flags); if (v) { adds(v); } return v; } void LookupSet::adds(Variable *v) { if (v->isOverloaded()) { SFOREACH_OBJLIST_NC(Variable, v->overload->set, iter) { add(iter.data()); } } else { add(v); } } void LookupSet::add(Variable *v) { // is 'v' already present? SFOREACH_OBJLIST(Variable, *this, iter) { if (sameEntity(v, iter.data())) { return; // already present } } // not already present, add it prepend(v); } void LookupSet::removeAllButOne() { while (count() > 1) { removeFirst(); } } void LookupSet::removeNonTemplates() { SObjListMutator mut(*this); while (!mut.isDone()) { Variable *v = mut.data(); if (v->isTemplate()) { mut.adv(); // keep it continue; } // 2005-04-17: in/t0055.cc: The context is a lookup that has // template arguments. It might be that we found a selfname in // the scope of a template class instantiation; but if template // args are used, then the user is intending to apply args to the // original template. (The code here is an approximation of what // is specified in 14.6p2b.) if (v->hasFlag(DF_SELFNAME)) { // argh.. my selfnames do not have proper template info, so // I have to go through the type (TODO: fix this) if (v->type->isCompoundType()) { CompoundType *ct = v->type->asCompoundType(); TemplateInfo *tinfo = ct->templateInfo(); if (tinfo != NULL && tinfo->isCompleteSpecOrInstantiation()) { // replace 'v' with a pointer to the template primary mut.dataRef() = tinfo->getPrimary()->var; mut.adv(); continue; } } // (in/t0501.cc) else if (v->type->isPseudoInstantiation()) { PseudoInstantiation *pi = v->type->asPseudoInstantiation(); mut.dataRef() = pi->primary->typedefVar; mut.adv(); continue; } else { xfailure("unexpected DF_SELFNAME variable type"); } } mut.remove(); // filter it out } } string LookupSet::asString() const { if (isEmpty()) { return ""; } // are all the names in the same scope? Scope *scope = firstC()->scope; SFOREACH_OBJLIST(Variable, *this, iter1) { Variable const *v = iter1.data(); if (v->scope != scope) { scope = NULL; } } stringBuilder sb; SFOREACH_OBJLIST(Variable, *this, iter2) { Variable const *v = iter2.data(); sb << " " << v->loc << ": "; if (scope) { sb << v->toString(); // all same scope, no need to prin it } else { sb << v->toQualifiedString(); } sb << "\n"; } return sb; } void LookupSet::gdb() const { cout << asString(); } // EOF