1 // =================================
 2 // Copyright (c) 2021 Seppo Laakko
 3 // Distributed under the MIT license
 4 // =================================
 5 
 6 #include <cmajor/binder/Access.hpp>
 7 #include <cmajor/symbols/ClassTypeSymbol.hpp>
 8 #include <cmajor/symbols/ClassTemplateSpecializationSymbol.hpp>
 9 #include <cmajor/symbols/Exception.hpp>
10 #include <soulng/util/Unicode.hpp>
11 
12 namespace cmajor { namespace binder {
13 
14 using namespace soulng::unicode;
15 
16 bool HasAccess(FunctionSymbol* fromFunctionSymbol* toSymbol)
17 {
18     if (!fromFunction) return false;
19     FunctionSymbol* toContainingFunction = toSymbol->ContainingFunctionNoThrow();
20     if (toContainingFunction)
21     {
22         if (fromFunction == toContainingFunction || FunctionSymbolsEqual()(fromFunctiontoContainingFunction))
23         {
24             return true;
25         }
26     }
27     ClassTypeSymbol* toContainingClass = toSymbol->ContainingClassNoThrow();
28     if (toContainingClass)
29     {
30         if (!HasAccess(fromFunctiontoContainingClass)) return false;
31     }
32     switch (toSymbol->DeclaredAccess())
33     {
34         case SymbolAccess::public_: return true;
35         case SymbolAccess::protected_:
36         {
37             ClassTypeSymbol* fromContainingClass = fromFunction->ContainingClassNoThrow();
38             if (fromContainingClass)
39             {
40                 if (toContainingClass && toContainingClass->IsSameParentOrAncestorOf(fromContainingClass))
41                 {
42                     return true;
43                 }
44                 if (fromContainingClass->HasBaseClass(toContainingClass))
45                 {
46                     return true;
47                 }
48             }
49             break;
50         }
51         case SymbolAccess::internal_:
52         {
53             if (fromFunction->GetModule() == toSymbol->GetModule())
54             {
55                 return true;;
56             }
57             break;
58         }
59         case SymbolAccess::private_:
60         {
61             if (toContainingClass)
62             {
63                 ClassTypeSymbol* fromContainingClass = fromFunction->ContainingClassNoThrow();
64                 if (fromContainingClass)
65                 {
66                     if (toContainingClass->IsSameParentOrAncestorOf(fromContainingClass))
67                     {
68                         return true;
69                     }
70                 }
71             }
72             break;
73         }
74     }
75     return false;
76 }
77 
78 void CheckAccess(FunctionSymbol* fromFunctionSymbol* toSymbol)
79 {
80     if (!HasAccess(fromFunctiontoSymbol))
81     {
82         throw Exception(toSymbol->TypeString() + " '" + ToUtf8(toSymbol->FullName()) + "' is inaccessible due to its protection level"
83             fromFunction->GetSpan()fromFunction->SourceModuleId()toSymbol->GetSpan()toSymbol->SourceModuleId());
84     }
85 }
86 
87 } } // namespace cmajor::binder