diff options
| author | _ov4 <ov4@ov4.org> | 2026-10-17 15:22:23 +0000 |
|---|---|---|
| committer | _ov4 <ov4@ov4.org> | 2026-10-17 15:22:23 +0000 |
| commit | f7f5df01c416a10e3eb9508a7a7150c792a8b4ca (patch) | |
| tree | 9d1fc624c74c129b24fe8b8a6f921f50b799e09a /lib/CodeGen/CodeGen.cc | |
| parent | 09498bb7aab9182ba172aae1045ca895d4f422d4 (diff) | |
feat(codegen): allow identical EXTERN redeclarations across files
Repeated EXTERN declarations with the same signature share one C symbol,
as C declarations do; conflicting signatures are errors.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'lib/CodeGen/CodeGen.cc')
| -rw-r--r-- | lib/CodeGen/CodeGen.cc | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/lib/CodeGen/CodeGen.cc b/lib/CodeGen/CodeGen.cc index 7abdad7..61fd837 100644 --- a/lib/CodeGen/CodeGen.cc +++ b/lib/CodeGen/CodeGen.cc @@ -187,14 +187,16 @@ void CodeGen::compile(const std::vector<SourceUnit> &Sources) { }); FuncGen->setVisibility([this](size_t Owner) { return isVisible(Owner); }); - struct Definition { size_t Unit; bool IsFunction; bool IsOverload; }; + struct Definition { size_t Unit; bool IsFunction; bool IsOverload; bool IsExtern; }; IdentifierMap<Definition> Definitions; std::optional<size_t> CodeUnit; FunctionDefAST *Entry = nullptr; size_t EntryUnit = 0; - auto Reserve = [&](const std::string &Name, bool IsFunction = false, bool IsOverload = false) { - auto [It, Added] = Definitions.emplace(Name, Definition{CurrentUnit, IsFunction, IsOverload}); - bool Compatible = IsFunction && IsOverload && It->second.IsFunction && It->second.IsOverload; + auto Reserve = [&](const std::string &Name, bool IsFunction = false, bool IsOverload = false, + bool IsExtern = false) { + auto [It, Added] = Definitions.emplace(Name, Definition{CurrentUnit, IsFunction, IsOverload, IsExtern}); + bool Compatible = (IsFunction && IsOverload && It->second.IsFunction && It->second.IsOverload) || + (IsExtern && It->second.IsExtern); if (!Added && It->second.Unit != CurrentUnit && !Compatible) reportError("Duplicate definition %s in %s and %s", Name.c_str(), Sources[It->second.Unit].Path.c_str(), Sources[CurrentUnit].Path.c_str()); @@ -216,7 +218,7 @@ void CodeGen::compile(const std::vector<SourceUnit> &Sources) { reportError("MAIN must be a FUNCTION with no parameters returning INTEGER"); } } else if (auto *X = dynamic_cast<ExternDeclAST*>(S.get())) { - Reserve(X->getProto()->getName(), true); + Reserve(X->getProto()->getName(), true, false, true); } else if (dynamic_cast<IncludeObjStmtAST*>(S.get())) { } else if (auto *E = dynamic_cast<EnumTypeDeclAST*>(S.get())) { TypeName = E->getName(); @@ -461,6 +463,8 @@ const FuncSig *CodeGen::resolveCall(const std::string &Name, return nullptr; } if (Overloads.size() == 1 && !Overloads.front()->IsOverload) return Overloads.front(); + // Visible EXTERN redeclarations are identical by construction. + if (Overloads.front()->IsExternal) return Overloads.front(); struct ArgumentType { const TypeInfo *Type; int Rank; }; std::vector<ArgumentType> Actual; std::string Key; |
