Start adding support for value overloading. Right now we allow overloaded definitions (at top level only), and name binding just takes the first value of a name.

Swift SVN r348
This commit is contained in:
Chris Lattner
2011-04-10 03:08:27 +00:00
parent e071e0f159
commit 229141ab80
2 changed files with 100 additions and 11 deletions

View File

@@ -108,10 +108,76 @@ ValueDecl *ReferencedModule::lookupValue(ImportDecl *ID, Identifier Name) {
}
namespace {
struct TinyVector {
typedef llvm::SmallVector<ValueDecl*, 4> VecTy;
llvm::PointerUnion<ValueDecl*, VecTy*> Val;
TinyVector() {}
TinyVector(const TinyVector &RHS) : Val(RHS.Val) {
if (VecTy *V = Val.dyn_cast<VecTy*>())
Val = new VecTy(*V);
}
~TinyVector() {
if (VecTy *V = Val.dyn_cast<VecTy*>())
delete V;
}
unsigned size() const {
if (Val.isNull())
return 0;
if (Val.is<ValueDecl*>())
return 1;
return Val.get<VecTy*>()->size();
}
ValueDecl *operator[](unsigned i) const {
assert(!Val.isNull() && "vector empty");
if (ValueDecl *V = Val.dyn_cast<ValueDecl*>()) {
assert(i == 0 && "tinyvector index out of range");
return V;
}
assert(i < Val.get<VecTy*>()->size() && "tinyvector index out of range");
return (*Val.get<VecTy*>())[i];
}
void push_back(ValueDecl *VD) {
assert(VD != 0 && "Can't add a null value");
// If we have nothing, add something.
if (Val.isNull()) {
Val = VD;
return;
}
// If we have a single value, convert to a vector.
if (ValueDecl *V = Val.dyn_cast<ValueDecl*>()) {
Val = new VecTy();
Val.get<VecTy*>()->push_back(V);
}
// Add the new value, we know we have a vector.
Val.get<VecTy*>()->push_back(VD);
}
ValueDecl *front() const {
assert(!Val.isNull() && "vector empty");
if (ValueDecl *V = Val.dyn_cast<ValueDecl*>())
return V;
return Val.get<VecTy*>()->front();
}
private:
void operator=(const TinyVector&); // DISABLED.
};
}
namespace {
class NameBinder {
std::vector<ReferencedModule *> LoadedModules;
/// TopLevelValues - This is the list of top-level declarations we have.
llvm::DenseMap<Identifier, ValueDecl *> TopLevelValues;
llvm::DenseMap<Identifier, TinyVector> TopLevelValues;
llvm::SmallVector<std::pair<ImportDecl*, ReferencedModule*>, 4> Imports;
public:
ASTContext &Context;
@@ -122,7 +188,7 @@ namespace {
}
void addNamedTopLevelDecl(ValueDecl *VD) {
TopLevelValues[VD->Name] = VD;
TopLevelValues[VD->Name].push_back(VD);
}
void addImport(ImportDecl *ID);
@@ -215,11 +281,11 @@ TypeAliasDecl *NameBinder::lookupTypeName(Identifier Name) {
/// returns a decl if found or null if not.
ValueDecl *NameBinder::bindValueName(Identifier Name) {
// Resolve forward references defined within the module.
llvm::DenseMap<Identifier, ValueDecl *>::iterator I =
llvm::DenseMap<Identifier, TinyVector>::iterator I =
TopLevelValues.find(Name);
// If we found a match, return the decl.
if (I != TopLevelValues.end())
return I->second;
return I->second.front();
// If we still haven't found it, scrape through all of the imports, taking the
// first match of the name.

View File

@@ -150,18 +150,41 @@ TypeAliasDecl *SemaDecl::LookupTypeName(Identifier Name, llvm::SMLoc Loc) {
return TAD;
}
static void DiagnoseRedefinition(ValueDecl *Prev, ValueDecl *New, SemaDecl &SD){
assert(New != Prev && "Cannot conflict with self");
if (New->Init)
SD.error(New->getLocStart(), "definition conflicts with previous value");
else
SD.error(New->getLocStart(), "declaration conflicts with previous value");
if (Prev->Init)
SD.note(Prev->getLocStart(), "previous definition here");
else
SD.note(Prev->getLocStart(), "previous declaration here");
}
/// AddToScope - Register the specified decl as being in the current lexical
/// scope.
void SemaDecl::AddToScope(ValueDecl *D) {
// If we have a shadowed variable definition, check to see if we have a
// redefinition: two definitions in the same scope with the same name.
std::pair<unsigned, ValueDecl*> Entry =
getValueHT(ValueScopeHT).lookup(D->Name);
if (Entry.second && Entry.first == CurScope->getDepth()) {
error(D->getLocStart(),
"variable declaration conflicts with previous declaration");
note(LookupValueName(D->Name)->getLocStart(), "previous declaration here");
return;
ValueScopeHTType &ValueHT = getValueHT(ValueScopeHT);
ValueScopeHTType::iterator EntryI = ValueHT.begin(D->Name);
// A redefinition is a hit in the scoped table at the same depth.
if (EntryI != ValueHT.end() && EntryI->first == CurScope->getDepth()) {
ValueDecl *PrevDecl = EntryI->second;
// If this is at top-level scope, we allow overloading. If not, we don't.
// FIXME: This should be tied to whether the scope corresponds to a
// DeclContext like a TranslationUnit or a Namespace. Add a bit to Scope
// to track this?
if (CurScope->getDepth() != 0)
return DiagnoseRedefinition(PrevDecl, D, *this);
// Note: we don't check whether all of the elements of the overload set have
// different types. This is checked later. We also don't check that all
// values found with unqualified lookup have the same infix-ness.
}
getValueHT(ValueScopeHT).insert(D->Name,