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