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+ void activateVariable (llvm::StringRef Name) {
32+ assert (InvisibleDeclarations.count (Name) &&
33+ InvisibleDeclarations.at (Name).size () == 1 );
34+ assert (Declarations.count (Name) == 0 || Declarations.at (Name).empty ());
35+
36+ Declarations[Name].emplace_back (InvisibleDeclarations.at (Name).front ());
37+ InvisibleDeclarations.erase (Name);
38+ }
39+
40+ bool isInvisible (llvm::StringRef Name) const {
41+ return InvisibleDeclarations.count (Name);
42+ }
43+
44+ bool registerDeclaration (const Decl *D, bool Invisible, bool Update) {
45+ return registerDeclaration (D, llvm::StringRef (), nullptr , Invisible,
46+ Update);
47+ }
48+
49+ bool registerDeclaration (const Decl *D, llvm::StringRef Name,
50+ const SourceRange *Loc, bool Invisible,
51+ bool Update) {
52+ if (Name.empty ()) {
53+ Name = D->getName ();
54+ }
55+
56+ if (Name.empty ())
57+ return true ;
58+
59+ if (Update) {
60+ assert (!dynamic_cast <const FunctionDecl *>(D) &&
61+ " Attempt to update function definition." );
62+ Declarations.erase (Name);
63+ InvisibleDeclarations.erase (Name);
64+ return true ;
65+ } else {
66+ if (conflictingDeclaration (D, Name))
67+ return false ;
68+ if (EnclosingContainer && D->isVisibleAsUnqualifiedName ()) {
69+ // assert(false && "TODO: isVisibleAsUnqualifiedName for struct");
70+ cerr << " TODO: isVisibleAsUnqualifiedName for struct" << endl;
71+ // deal with homonymCandidates
72+ }
73+ }
74+
75+ std::vector<const Decl *> &Decls =
76+ Invisible ? InvisibleDeclarations[Name] : Declarations[Name];
77+ if (find (Decls.begin (), Decls.end (), D) == Decls.end ())
78+ Decls.emplace_back (D);
79+ return true ;
80+ }
81+
82+ std::vector<const Decl *>
83+ resolveName (llvm::StringRef Name, bool Recursive = false ,
84+ bool AlsoInvisible = false ,
85+ bool OnlyVisibleAsUnqualifiedNames = false ) const {
86+ std::vector<const Decl *> Res;
87+
88+ if (Declarations.count (Name)) {
89+ for (auto E : Declarations.at (Name)) {
90+ if (OnlyVisibleAsUnqualifiedNames) {
91+ if (!E->isVisibleAsUnqualifiedName ())
92+ continue ;
93+ }
94+ Res.emplace_back (E);
95+ }
96+ }
97+
98+ if (AlsoInvisible && InvisibleDeclarations.count (Name)) {
99+ for (auto E : InvisibleDeclarations.at (Name)) {
100+ if (OnlyVisibleAsUnqualifiedNames) {
101+ if (!E->isVisibleAsUnqualifiedName ())
102+ continue ;
103+ }
104+ Res.emplace_back (E);
105+ }
106+ }
107+
108+ if (Res.empty () && Recursive && EnclosingContainer)
109+ Res = EnclosingContainer->resolveName (Name, true , AlsoInvisible,
110+ OnlyVisibleAsUnqualifiedNames);
111+
112+ return Res;
113+ }
114+
115+ const Decl *conflictingDeclaration (const Decl *D,
116+ llvm::StringRef Name) const {
117+ if (Name.empty ())
118+ Name = D->getName ();
119+ assert (!Name.empty ());
120+
121+ std::vector<Decl const *> Decls;
122+ if (Declarations.count (Name))
123+ Decls += Declarations.at (Name);
124+
125+ if (InvisibleDeclarations.count (Name))
126+ Decls += InvisibleDeclarations.at (Name);
127+
128+ if (dynamic_cast <const FunctionDecl *>(D) ||
129+ dynamic_cast <const EventDecl *>(D) ||
130+ dynamic_cast <const MagicVariableDecl *>(D)) {
131+ for (const Decl *RegDecl : Decls) {
132+ if (dynamic_cast <const FunctionDecl *>(D) &&
133+ !dynamic_cast <const FunctionDecl *>(RegDecl))
134+ return RegDecl;
135+ if (dynamic_cast <const EventDecl *>(D) &&
136+ !dynamic_cast <const EventDecl *>(RegDecl))
137+ return RegDecl;
138+ if (dynamic_cast <const MagicVariableDecl *>(D) &&
139+ !dynamic_cast <const MagicVariableDecl *>(RegDecl))
140+ return RegDecl;
141+ }
142+ } else if (Decls.size () == 1 && Decls.front () == D) {
143+ return nullptr ;
144+ } else if (!Decls.empty ()) {
145+ return Decls.front ();
146+ }
147+
148+ return nullptr ;
149+ }
150+
151+ private:
152+ const ASTNode *EnclosingNode = nullptr ;
153+ const DeclarationContainer *EnclosingContainer = nullptr ;
154+ std::vector<const DeclarationContainer *> InnerContainers;
155+ std::map<llvm::StringRef, std::vector<const Decl *>> Declarations;
156+ std::map<llvm::StringRef, std::vector<const Decl *>> InvisibleDeclarations;
157+ // std::vector<std::tuple<std::string, langutil::SourceLocation const*>>
158+ // m_homonymCandidates;
159+ };
160+
161+ } // namespace soll
0 commit comments