tools/icheck/parser/src/shared/cplusplus/Scope.cpp
changeset 0 876b1a06bc25
equal deleted inserted replaced
-1:000000000000 0:876b1a06bc25
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Mobility Components.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 // Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
       
    42 //
       
    43 // Permission is hereby granted, free of charge, to any person obtaining a copy
       
    44 // of this software and associated documentation files (the "Software"), to deal
       
    45 // in the Software without restriction, including without limitation the rights
       
    46 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       
    47 // copies of the Software, and to permit persons to whom the Software is
       
    48 // furnished to do so, subject to the following conditions:
       
    49 //
       
    50 // The above copyright notice and this permission notice shall be included in
       
    51 // all copies or substantial portions of the Software.
       
    52 //
       
    53 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       
    54 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       
    55 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
       
    56 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
       
    57 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
       
    58 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
       
    59 // THE SOFTWARE.
       
    60 
       
    61 #include "Scope.h"
       
    62 #include "Symbols.h"
       
    63 #include "Names.h"
       
    64 #include "Literals.h"
       
    65 #include <cassert>
       
    66 #include <cstring>
       
    67 
       
    68 using namespace CPlusPlus;
       
    69 
       
    70 Scope::Scope(ScopedSymbol *owner)
       
    71     : _owner(owner),
       
    72       _symbols(0),
       
    73       _allocatedSymbols(0),
       
    74       _symbolCount(-1),
       
    75       _hash(0),
       
    76       _hashSize(0)
       
    77 { }
       
    78 
       
    79 Scope::~Scope()
       
    80 {
       
    81     if (_symbols)
       
    82         free(_symbols);
       
    83     if (_hash)
       
    84         free(_hash);
       
    85 }
       
    86 
       
    87 ScopedSymbol *Scope::owner() const
       
    88 { return _owner; }
       
    89 
       
    90 void Scope::setOwner(ScopedSymbol *owner)
       
    91 { _owner = owner; }
       
    92 
       
    93 Scope *Scope::enclosingScope() const
       
    94 {
       
    95     if (! _owner)
       
    96         return 0;
       
    97 
       
    98     return _owner->scope();
       
    99 }
       
   100 
       
   101 Scope *Scope::enclosingNamespaceScope() const
       
   102 {
       
   103     Scope *scope = enclosingScope();
       
   104     for (; scope; scope = scope->enclosingScope()) {
       
   105         if (scope->owner()->isNamespace())
       
   106             break;
       
   107     }
       
   108     return scope;
       
   109 }
       
   110 
       
   111 Scope *Scope::enclosingClassScope() const
       
   112 {
       
   113     Scope *scope = enclosingScope();
       
   114     for (; scope; scope = scope->enclosingScope()) {
       
   115         if (scope->owner()->isClass())
       
   116             break;
       
   117     }
       
   118     return scope;
       
   119 }
       
   120 
       
   121 Scope *Scope::enclosingEnumScope() const
       
   122 {
       
   123     Scope *scope = enclosingScope();
       
   124     for (; scope; scope = scope->enclosingScope()) {
       
   125         if (scope->owner()->isEnum())
       
   126             break;
       
   127     }
       
   128     return scope;
       
   129 }
       
   130 
       
   131 Scope *Scope::enclosingFunctionScope() const
       
   132 {
       
   133     Scope *scope = enclosingScope();
       
   134     for (; scope; scope = scope->enclosingScope()) {
       
   135         if (scope->owner()->isFunction())
       
   136             break;
       
   137     }
       
   138     return scope;
       
   139 }
       
   140 
       
   141 Scope *Scope::enclosingBlockScope() const
       
   142 {
       
   143     Scope *scope = enclosingScope();
       
   144     for (; scope; scope = scope->enclosingScope()) {
       
   145         if (scope->owner()->isBlock())
       
   146             break;
       
   147     }
       
   148     return scope;
       
   149 }
       
   150 
       
   151 bool Scope::isNamespaceScope() const
       
   152 {
       
   153     if (_owner)
       
   154         return _owner->isNamespace();
       
   155     return false;
       
   156 }
       
   157 
       
   158 bool Scope::isClassScope() const
       
   159 {
       
   160     if (_owner)
       
   161         return _owner->isClass();
       
   162     return false;
       
   163 }
       
   164 
       
   165 bool Scope::isEnumScope() const
       
   166 {
       
   167     if (_owner)
       
   168         return _owner->isEnum();
       
   169     return false;
       
   170 }
       
   171 
       
   172 bool Scope::isBlockScope() const
       
   173 {
       
   174     if (_owner)
       
   175         return _owner->isBlock();
       
   176     return false;
       
   177 }
       
   178 
       
   179 bool Scope::isPrototypeScope() const
       
   180 {
       
   181     Function *f = 0;
       
   182     if (_owner && 0 != (f = _owner->asFunction()))
       
   183         return f->arguments() == this;
       
   184     return false;
       
   185 }
       
   186 
       
   187 bool Scope::isObjCClassScope() const
       
   188 {
       
   189     if (_owner)
       
   190         return _owner->isObjCClass();
       
   191     return false;
       
   192 }
       
   193 
       
   194 bool Scope::isFunctionScope() const
       
   195 {
       
   196     Function *f = 0;
       
   197     if (_owner && 0 != (f = _owner->asFunction()))
       
   198         return f->arguments() != this;
       
   199     return false;
       
   200 }
       
   201 
       
   202 bool Scope::isObjCMethodScope() const
       
   203 {
       
   204     ObjCMethod *m = 0;
       
   205     if (_owner && 0 != (m = _owner->asObjCMethod()))
       
   206         return m->arguments() != this;
       
   207     return false;
       
   208 }
       
   209 
       
   210 void Scope::enterSymbol(Symbol *symbol)
       
   211 {
       
   212     if (++_symbolCount == _allocatedSymbols) {
       
   213         _allocatedSymbols <<= 1;
       
   214         if (! _allocatedSymbols)
       
   215             _allocatedSymbols = DefaultInitialSize;
       
   216 
       
   217         _symbols = reinterpret_cast<Symbol **>(realloc(_symbols, sizeof(Symbol *) * _allocatedSymbols));
       
   218     }
       
   219 
       
   220     assert(! symbol->_scope || symbol->scope() == this);
       
   221     symbol->_index = _symbolCount;
       
   222     symbol->_scope = this;
       
   223     _symbols[_symbolCount] = symbol;
       
   224 
       
   225     if (_symbolCount >= _hashSize * 0.6)
       
   226         rehash();
       
   227     else {
       
   228         const unsigned h = hashValue(symbol);
       
   229         symbol->_next = _hash[h];
       
   230         _hash[h] = symbol;
       
   231     }
       
   232 }
       
   233 
       
   234 Symbol *Scope::lookat(const Name *name) const
       
   235 {
       
   236     if (! name)
       
   237         return 0;
       
   238 
       
   239     else if (const OperatorNameId *opId = name->asOperatorNameId())
       
   240         return lookat(opId->kind());
       
   241 
       
   242     else if (const Identifier *id = name->identifier())
       
   243         return lookat(id);
       
   244 
       
   245     else
       
   246         return 0;
       
   247 }
       
   248 
       
   249 Symbol *Scope::lookat(const Identifier *id) const
       
   250 {
       
   251     if (! _hash || ! id)
       
   252         return 0;
       
   253 
       
   254     const unsigned h = id->hashCode() % _hashSize;
       
   255     Symbol *symbol = _hash[h];
       
   256     for (; symbol; symbol = symbol->_next) {
       
   257         const Name *identity = symbol->identity();
       
   258         if (! identity) {
       
   259             continue;
       
   260         } else if (const NameId *nameId = identity->asNameId()) {
       
   261             if (nameId->identifier()->isEqualTo(id))
       
   262                 break;
       
   263         } else if (const TemplateNameId *t = identity->asTemplateNameId()) {
       
   264             if (t->identifier()->isEqualTo(id))
       
   265                 break;
       
   266         } else if (const DestructorNameId *d = identity->asDestructorNameId()) {
       
   267             if (d->identifier()->isEqualTo(id))
       
   268                 break;
       
   269         } else if (identity->isQualifiedNameId()) {
       
   270             return 0;
       
   271         } else if (const SelectorNameId *selectorNameId = identity->asSelectorNameId()) {
       
   272             if (selectorNameId->identifier()->isEqualTo(id))
       
   273                 break;
       
   274         }
       
   275     }
       
   276     return symbol;
       
   277 }
       
   278 
       
   279 Symbol *Scope::lookat(int operatorId) const
       
   280 {
       
   281     if (! _hash)
       
   282         return 0;
       
   283 
       
   284     const unsigned h = operatorId % _hashSize;
       
   285     Symbol *symbol = _hash[h];
       
   286     for (; symbol; symbol = symbol->_next) {
       
   287         const Name *identity = symbol->identity();
       
   288         if (const OperatorNameId *op = identity->asOperatorNameId()) {
       
   289             if (op->kind() == operatorId)
       
   290                 break;
       
   291         }
       
   292     }
       
   293     return symbol;
       
   294 }
       
   295 
       
   296 void Scope::rehash()
       
   297 {
       
   298     _hashSize <<= 1;
       
   299 
       
   300     if (! _hashSize)
       
   301         _hashSize = DefaultInitialSize;
       
   302 
       
   303     _hash = reinterpret_cast<Symbol **>(realloc(_hash, sizeof(Symbol *) * _hashSize));
       
   304     std::memset(_hash, 0, sizeof(Symbol *) * _hashSize);
       
   305 
       
   306     for (int index = 0; index < _symbolCount + 1; ++index) {
       
   307         Symbol *symbol = _symbols[index];
       
   308         const unsigned h = hashValue(symbol);
       
   309         symbol->_next = _hash[h];
       
   310         _hash[h] = symbol;
       
   311     }
       
   312 }
       
   313 
       
   314 unsigned Scope::hashValue(Symbol *symbol) const
       
   315 {
       
   316     if (! symbol)
       
   317         return 0;
       
   318 
       
   319     return symbol->hashCode() % _hashSize;
       
   320 }
       
   321 
       
   322 bool Scope::isEmpty() const
       
   323 { return _symbolCount == -1; }
       
   324 
       
   325 unsigned Scope::symbolCount() const
       
   326 { return _symbolCount + 1; }
       
   327 
       
   328 Symbol *Scope::symbolAt(unsigned index) const
       
   329 {
       
   330     if (! _symbols)
       
   331         return 0;
       
   332     return _symbols[index];
       
   333 }
       
   334 
       
   335 Scope::iterator Scope::firstSymbol() const
       
   336 { return _symbols; }
       
   337 
       
   338 Scope::iterator Scope::lastSymbol() const
       
   339 { return _symbols + _symbolCount + 1; }
       
   340 
       
   341