1+ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2+ #pragma once
3+
4+ #include " soll/AST/AST.h"
5+ #include " soll/AST/Decl.h"
6+ #include " soll/Basic/DiagnosticSema.h"
7+ #include " soll/Sema/Sema.h"
8+
9+ #include < iostream>
10+ #include < map>
11+ #include < memory>
12+ #include < string>
13+ #include < vector>
14+ using std::cerr;
15+ using std::endl;
16+
17+ namespace soll {
18+
19+ class DeclarationContainer {
20+ public:
21+ DeclarationContainer () = default ;
22+ explicit DeclarationContainer (const ASTNode *EnclosingNode,
23+ DeclarationContainer *EnclosingContainer)
24+ : EnclosingNode(EnclosingNode), EnclosingContainer(EnclosingContainer) {
25+ if (EnclosingContainer)
26+ EnclosingContainer->InnerContainers .emplace_back (this );
27+ }
28+
29+ ASTNode const *enclosingNode () const { return EnclosingNode; }
30+
31+ bool registerDeclaration (const Decl *D, bool Invisible, bool Update) {
32+ return registerDeclaration (D, llvm::StringRef (), nullptr , Invisible,
33+ Update);
34+ }
35+
36+ bool registerDeclaration (const Decl *D, llvm::StringRef Name,
37+ const SourceRange *Loc, bool Invisible, bool Update) {
38+ if (Name.empty ()) {
39+ Name = D->getName ();
40+ }
41+
42+ if (Name.empty ())
43+ return true ;
44+
45+ if (Update) {
46+ assert (!dynamic_cast <const FunctionDecl *>(D) &&
47+ " Attempt to update function definition." );
48+ Declarations.erase (Name);
49+ InvisibleDeclarations.erase (Name);
50+ return true ;
51+ } else {
52+ if (conflictingDeclaration (D, Name))
53+ return false ;
54+ if (EnclosingContainer && D->isVisibleAsUnqualifiedName ()) {
55+ // assert(false && "TODO: isVisibleAsUnqualifiedName for struct");
56+ cerr << " TODO: isVisibleAsUnqualifiedName for struct" << endl;
57+ // deal with homonymCandidates
58+ }
59+ }
60+
61+ std::vector<const Decl *> Decls =
62+ Invisible ? InvisibleDeclarations[Name] : Declarations[Name];
63+ if (find (Decls.begin (), Decls.end (), D) != Decls.end ())
64+ Decls.emplace_back (D);
65+
66+ return true ;
67+ }
68+
69+ const Decl *conflictingDeclaration (const Decl *D,
70+ llvm::StringRef Name) const {
71+ if (Name.empty ())
72+ Name = D->getName ();
73+ assert (!Name.empty ());
74+
75+ std::vector<Decl const *> Decls;
76+ if (Declarations.count (Name))
77+ Decls += Declarations.at (Name);
78+
79+ if (InvisibleDeclarations.count (Name))
80+ Decls += InvisibleDeclarations.at (Name);
81+
82+ if (dynamic_cast <const FunctionDecl *>(D) ||
83+ dynamic_cast <const EventDecl *>(D) ||
84+ dynamic_cast <const MagicVariableDecl *>(D)) {
85+ for (const Decl *RegDecl : Decls) {
86+ if (dynamic_cast <const FunctionDecl *>(D) &&
87+ !dynamic_cast <const FunctionDecl *>(RegDecl))
88+ return RegDecl;
89+ if (dynamic_cast <const EventDecl *>(D) &&
90+ !dynamic_cast <const EventDecl *>(RegDecl))
91+ return RegDecl;
92+ if (dynamic_cast <const MagicVariableDecl *>(D) &&
93+ !dynamic_cast <const MagicVariableDecl *>(RegDecl))
94+ return RegDecl;
95+ }
96+ } else if (Decls.size () == 1 && Decls.front () == D) {
97+ return nullptr ;
98+ } else if (!Decls.empty ()) {
99+ return Decls.front ();
100+ }
101+
102+ return nullptr ;
103+ }
104+
105+ private:
106+ const ASTNode *EnclosingNode = nullptr ;
107+ const DeclarationContainer *EnclosingContainer = nullptr ;
108+ std::vector<const DeclarationContainer *> InnerContainers;
109+ std::map<llvm::StringRef, std::vector<const Decl *>> Declarations;
110+ std::map<llvm::StringRef, std::vector<const Decl *>> InvisibleDeclarations;
111+ // std::vector<std::tuple<std::string, langutil::SourceLocation const*>>
112+ // m_homonymCandidates;
113+ };
114+
115+ } // namespace soll
0 commit comments