tools/icheck/parser/src/shared/cplusplus/CheckName.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 "CheckName.h"
       
    62 #include "Semantic.h"
       
    63 #include "AST.h"
       
    64 #include "Control.h"
       
    65 #include "TranslationUnit.h"
       
    66 #include "Literals.h"
       
    67 #include "Names.h"
       
    68 #include "CoreTypes.h"
       
    69 #include "Symbols.h"
       
    70 #include "Scope.h"
       
    71 #include <cassert>
       
    72 
       
    73 using namespace CPlusPlus;
       
    74 
       
    75 CheckName::CheckName(Semantic *semantic)
       
    76     : SemanticCheck(semantic),
       
    77       _name(0),
       
    78       _scope(0)
       
    79 { }
       
    80 
       
    81 CheckName::~CheckName()
       
    82 { }
       
    83 
       
    84 const Name *CheckName::check(NameAST *name, Scope *scope)
       
    85 {
       
    86     const Name *previousName = switchName(0);
       
    87     Scope *previousScope = switchScope(scope);
       
    88     accept(name);
       
    89 
       
    90     if (_name && name)
       
    91         name->name = _name;
       
    92 
       
    93     (void) switchScope(previousScope);
       
    94     return switchName(previousName);
       
    95 }
       
    96 
       
    97 const Name *CheckName::check(NestedNameSpecifierListAST *nested_name_specifier_list, Scope *scope)
       
    98 {
       
    99     const Name *previousName = switchName(0);
       
   100     Scope *previousScope = switchScope(scope);
       
   101 
       
   102     std::vector<const Name *> names;
       
   103     for (NestedNameSpecifierListAST *it = nested_name_specifier_list; it; it = it->next) {
       
   104         NestedNameSpecifierAST *nested_name_specifier = it->value;
       
   105         names.push_back(semantic()->check(nested_name_specifier->class_or_namespace_name, _scope));
       
   106     }
       
   107 
       
   108     if (! names.empty())
       
   109         _name = control()->qualifiedNameId(&names[0], names.size());
       
   110 
       
   111     (void) switchScope(previousScope);
       
   112     return switchName(previousName);
       
   113 }
       
   114 
       
   115 const Name *CheckName::check(ObjCSelectorAST *args, Scope *scope)
       
   116 {
       
   117     const Name *previousName = switchName(0);
       
   118     Scope *previousScope = switchScope(scope);
       
   119 
       
   120     accept(args);
       
   121 
       
   122     (void) switchScope(previousScope);
       
   123     return switchName(previousName);
       
   124 }
       
   125 
       
   126 void CheckName::check(ObjCMessageArgumentDeclarationAST *arg, Scope *scope)
       
   127 {
       
   128     const Name *previousName = switchName(0);
       
   129     Scope *previousScope = switchScope(scope);
       
   130 
       
   131     accept(arg);
       
   132 
       
   133     (void) switchScope(previousScope);
       
   134     (void) switchName(previousName);
       
   135 }
       
   136 
       
   137 const Name *CheckName::switchName(const Name *name)
       
   138 {
       
   139     const Name *previousName = _name;
       
   140     _name = name;
       
   141     return previousName;
       
   142 }
       
   143 
       
   144 Scope *CheckName::switchScope(Scope *scope)
       
   145 {
       
   146     Scope *previousScope = _scope;
       
   147     _scope = scope;
       
   148     return previousScope;
       
   149 }
       
   150 
       
   151 bool CheckName::visit(QualifiedNameAST *ast)
       
   152 {
       
   153     std::vector<const Name *> names;
       
   154     for (NestedNameSpecifierListAST *it = ast->nested_name_specifier_list; it; it = it->next) {
       
   155         NestedNameSpecifierAST *nested_name_specifier = it->value;
       
   156         names.push_back(semantic()->check(nested_name_specifier->class_or_namespace_name, _scope));
       
   157     }
       
   158     names.push_back(semantic()->check(ast->unqualified_name, _scope));
       
   159     _name = control()->qualifiedNameId(&names[0], names.size(), ast->global_scope_token != 0);
       
   160 
       
   161     ast->name = _name;
       
   162     return false;
       
   163 }
       
   164 
       
   165 bool CheckName::visit(OperatorFunctionIdAST *ast)
       
   166 {
       
   167     assert(ast->op != 0);
       
   168 
       
   169     OperatorNameId::Kind kind = OperatorNameId::InvalidOp;
       
   170 
       
   171     switch (tokenKind(ast->op->op_token)) {
       
   172     case T_NEW:
       
   173         if (ast->op->open_token)
       
   174             kind = OperatorNameId::NewArrayOp;
       
   175         else
       
   176             kind = OperatorNameId::NewOp;
       
   177         break;
       
   178 
       
   179     case T_DELETE:
       
   180         if (ast->op->open_token)
       
   181             kind = OperatorNameId::DeleteArrayOp;
       
   182         else
       
   183             kind = OperatorNameId::DeleteOp;
       
   184         break;
       
   185 
       
   186     case T_PLUS:
       
   187         kind = OperatorNameId::PlusOp;
       
   188         break;
       
   189 
       
   190     case T_MINUS:
       
   191         kind = OperatorNameId::MinusOp;
       
   192         break;
       
   193 
       
   194     case T_STAR:
       
   195         kind = OperatorNameId::StarOp;
       
   196         break;
       
   197 
       
   198     case T_SLASH:
       
   199         kind = OperatorNameId::SlashOp;
       
   200         break;
       
   201 
       
   202     case T_PERCENT:
       
   203         kind = OperatorNameId::PercentOp;
       
   204         break;
       
   205 
       
   206     case T_CARET:
       
   207         kind = OperatorNameId::CaretOp;
       
   208         break;
       
   209 
       
   210     case T_AMPER:
       
   211         kind = OperatorNameId::AmpOp;
       
   212         break;
       
   213 
       
   214     case T_PIPE:
       
   215         kind = OperatorNameId::PipeOp;
       
   216         break;
       
   217 
       
   218     case T_TILDE:
       
   219         kind = OperatorNameId::TildeOp;
       
   220         break;
       
   221 
       
   222     case T_EXCLAIM:
       
   223         kind = OperatorNameId::ExclaimOp;
       
   224         break;
       
   225 
       
   226     case T_EQUAL:
       
   227         kind = OperatorNameId::EqualOp;
       
   228         break;
       
   229 
       
   230     case T_LESS:
       
   231         kind = OperatorNameId::LessOp;
       
   232         break;
       
   233 
       
   234     case T_GREATER:
       
   235         kind = OperatorNameId::GreaterOp;
       
   236         break;
       
   237 
       
   238     case T_PLUS_EQUAL:
       
   239         kind = OperatorNameId::PlusEqualOp;
       
   240         break;
       
   241 
       
   242     case T_MINUS_EQUAL:
       
   243         kind = OperatorNameId::MinusEqualOp;
       
   244         break;
       
   245 
       
   246     case T_STAR_EQUAL:
       
   247         kind = OperatorNameId::StarEqualOp;
       
   248         break;
       
   249 
       
   250     case T_SLASH_EQUAL:
       
   251         kind = OperatorNameId::SlashEqualOp;
       
   252         break;
       
   253 
       
   254     case T_PERCENT_EQUAL:
       
   255         kind = OperatorNameId::PercentEqualOp;
       
   256         break;
       
   257 
       
   258     case T_CARET_EQUAL:
       
   259         kind = OperatorNameId::CaretEqualOp;
       
   260         break;
       
   261 
       
   262     case T_AMPER_EQUAL:
       
   263         kind = OperatorNameId::AmpEqualOp;
       
   264         break;
       
   265 
       
   266     case T_PIPE_EQUAL:
       
   267         kind = OperatorNameId::PipeEqualOp;
       
   268         break;
       
   269 
       
   270     case T_LESS_LESS:
       
   271         kind = OperatorNameId::LessLessOp;
       
   272         break;
       
   273 
       
   274     case T_GREATER_GREATER:
       
   275         kind = OperatorNameId::GreaterGreaterOp;
       
   276         break;
       
   277 
       
   278     case T_LESS_LESS_EQUAL:
       
   279         kind = OperatorNameId::LessLessEqualOp;
       
   280         break;
       
   281 
       
   282     case T_GREATER_GREATER_EQUAL:
       
   283         kind = OperatorNameId::GreaterGreaterEqualOp;
       
   284         break;
       
   285 
       
   286     case T_EQUAL_EQUAL:
       
   287         kind = OperatorNameId::EqualEqualOp;
       
   288         break;
       
   289 
       
   290     case T_EXCLAIM_EQUAL:
       
   291         kind = OperatorNameId::ExclaimEqualOp;
       
   292         break;
       
   293 
       
   294     case T_LESS_EQUAL:
       
   295         kind = OperatorNameId::LessEqualOp;
       
   296         break;
       
   297 
       
   298     case T_GREATER_EQUAL:
       
   299         kind = OperatorNameId::GreaterEqualOp;
       
   300         break;
       
   301 
       
   302     case T_AMPER_AMPER:
       
   303         kind = OperatorNameId::AmpAmpOp;
       
   304         break;
       
   305 
       
   306     case T_PIPE_PIPE:
       
   307         kind = OperatorNameId::PipePipeOp;
       
   308         break;
       
   309 
       
   310     case T_PLUS_PLUS:
       
   311         kind = OperatorNameId::PlusPlusOp;
       
   312         break;
       
   313 
       
   314     case T_MINUS_MINUS:
       
   315         kind = OperatorNameId::MinusMinusOp;
       
   316         break;
       
   317 
       
   318     case T_COMMA:
       
   319         kind = OperatorNameId::CommaOp;
       
   320         break;
       
   321 
       
   322     case T_ARROW_STAR:
       
   323         kind = OperatorNameId::ArrowStarOp;
       
   324         break;
       
   325 
       
   326     case T_ARROW:
       
   327         kind = OperatorNameId::ArrowOp;
       
   328         break;
       
   329 
       
   330     case T_LPAREN:
       
   331         kind = OperatorNameId::FunctionCallOp;
       
   332         break;
       
   333 
       
   334     case T_LBRACKET:
       
   335         kind = OperatorNameId::ArrayAccessOp;
       
   336         break;
       
   337 
       
   338     default:
       
   339         kind = OperatorNameId::InvalidOp;
       
   340     } // switch
       
   341 
       
   342     _name = control()->operatorNameId(kind);
       
   343     ast->name = _name;
       
   344     return false;
       
   345 }
       
   346 
       
   347 bool CheckName::visit(ConversionFunctionIdAST *ast)
       
   348 {
       
   349     FullySpecifiedType ty = semantic()->check(ast->type_specifier_list, _scope);
       
   350     ty = semantic()->check(ast->ptr_operator_list, ty, _scope);
       
   351     _name = control()->conversionNameId(ty);
       
   352     return false;
       
   353 }
       
   354 
       
   355 bool CheckName::visit(SimpleNameAST *ast)
       
   356 {
       
   357     const Identifier *id = identifier(ast->identifier_token);
       
   358     _name = control()->nameId(id);
       
   359     ast->name = _name;
       
   360     return false;
       
   361 }
       
   362 
       
   363 bool CheckName::visit(DestructorNameAST *ast)
       
   364 {
       
   365     const Identifier *id = identifier(ast->identifier_token);
       
   366     _name = control()->destructorNameId(id);
       
   367     ast->name = _name;
       
   368     return false;
       
   369 }
       
   370 
       
   371 bool CheckName::visit(TemplateIdAST *ast)
       
   372 {
       
   373     const Identifier *id = identifier(ast->identifier_token);
       
   374     std::vector<FullySpecifiedType> templateArguments;
       
   375     for (TemplateArgumentListAST *it = ast->template_argument_list; it;
       
   376             it = it->next) {
       
   377         ExpressionAST *arg = it->value;
       
   378         FullySpecifiedType exprTy = semantic()->check(arg, _scope);
       
   379         templateArguments.push_back(exprTy);
       
   380     }
       
   381     if (templateArguments.empty())
       
   382         _name = control()->templateNameId(id);
       
   383     else
       
   384         _name = control()->templateNameId(id, &templateArguments[0],
       
   385                                           templateArguments.size());
       
   386     ast->name = _name;
       
   387     return false;
       
   388 }
       
   389 
       
   390 bool CheckName::visit(ObjCSelectorWithoutArgumentsAST *ast)
       
   391 {
       
   392     if (ast->name_token) {
       
   393         std::vector<const Name *> names;
       
   394         const Identifier *id = control()->findOrInsertIdentifier(spell(ast->name_token));
       
   395         const NameId *nameId = control()->nameId(id);
       
   396         names.push_back(nameId);
       
   397         _name = control()->selectorNameId(&names[0], names.size(), false);
       
   398         ast->selector_name = _name;
       
   399     }
       
   400 
       
   401     return false;
       
   402 }
       
   403 
       
   404 bool CheckName::visit(ObjCSelectorWithArgumentsAST *ast)
       
   405 {
       
   406     std::vector<const Name *> names;
       
   407     for (ObjCSelectorArgumentListAST *it = ast->selector_argument_list; it; it = it->next) {
       
   408         if (it->value->name_token) {
       
   409             const Identifier *id = control()->findOrInsertIdentifier(spell(it->value->name_token));
       
   410             const NameId *nameId = control()->nameId(id);
       
   411             names.push_back(nameId);
       
   412         } else {
       
   413             // we have an incomplete name due, probably due to error recovery. So, back out completely
       
   414             return false;
       
   415         }
       
   416     }
       
   417 
       
   418     if (!names.empty()) {
       
   419         _name = control()->selectorNameId(&names[0], names.size(), true);
       
   420         ast->selector_name = _name;
       
   421     }
       
   422 
       
   423     return false;
       
   424 }
       
   425 
       
   426 bool CheckName::visit(ObjCMessageArgumentDeclarationAST *ast)
       
   427 {
       
   428     FullySpecifiedType type;
       
   429 
       
   430     if (ast->type_name)
       
   431         type = semantic()->check(ast->type_name, _scope);
       
   432 
       
   433     if (ast->param_name_token) {
       
   434         const Identifier *id = identifier(ast->param_name_token);
       
   435         _name = control()->nameId(id);
       
   436         ast->name = _name;
       
   437 
       
   438         Argument *arg = control()->newArgument(ast->param_name_token, _name);
       
   439         ast->argument = arg;
       
   440         arg->setType(type);
       
   441         arg->setInitializer(0);
       
   442         _scope->enterSymbol(arg);
       
   443     }
       
   444 
       
   445     return false;
       
   446 }
       
   447 
       
   448