mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
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:
@@ -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.
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user