tools/icheck/parser/src/shared/cplusplus/CheckDeclaration.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 "CheckDeclaration.h"
       
    62 #include "Semantic.h"
       
    63 #include "AST.h"
       
    64 #include "TranslationUnit.h"
       
    65 #include "Scope.h"
       
    66 #include "Names.h"
       
    67 #include "CoreTypes.h"
       
    68 #include "Symbols.h"
       
    69 #include "Control.h"
       
    70 #include "Literals.h"
       
    71 #include <string>
       
    72 #include <cassert>
       
    73 
       
    74 using namespace CPlusPlus;
       
    75 
       
    76 CheckDeclaration::CheckDeclaration(Semantic *semantic)
       
    77     : SemanticCheck(semantic),
       
    78       _declaration(0),
       
    79       _scope(0),
       
    80       _templateParameters(0),
       
    81       _checkAnonymousArguments(false)
       
    82 { }
       
    83 
       
    84 CheckDeclaration::~CheckDeclaration()
       
    85 { }
       
    86 
       
    87 void CheckDeclaration::check(DeclarationAST *declaration,
       
    88                              Scope *scope, TemplateParameters *templateParameters)
       
    89 {
       
    90     Scope *previousScope = switchScope(scope);
       
    91     TemplateParameters *previousTemplateParameters = switchTemplateParameters(templateParameters);
       
    92     DeclarationAST *previousDeclaration = switchDeclaration(declaration);
       
    93     accept(declaration);
       
    94     (void) switchDeclaration(previousDeclaration);
       
    95     (void) switchTemplateParameters(previousTemplateParameters);
       
    96     (void) switchScope(previousScope);
       
    97 }
       
    98 
       
    99 DeclarationAST *CheckDeclaration::switchDeclaration(DeclarationAST *declaration)
       
   100 {
       
   101     DeclarationAST *previousDeclaration = _declaration;
       
   102     _declaration = declaration;
       
   103     return previousDeclaration;
       
   104 }
       
   105 
       
   106 Scope *CheckDeclaration::switchScope(Scope *scope)
       
   107 {
       
   108     Scope *previousScope = _scope;
       
   109     _scope = scope;
       
   110     return previousScope;
       
   111 }
       
   112 
       
   113 TemplateParameters *CheckDeclaration::switchTemplateParameters(TemplateParameters *templateParameters)
       
   114 {
       
   115     TemplateParameters *previousTemplateParameters = _templateParameters;
       
   116     _templateParameters = templateParameters;
       
   117     return previousTemplateParameters;
       
   118 }
       
   119 
       
   120 void CheckDeclaration::checkFunctionArguments(Function *fun)
       
   121 {
       
   122     if (! _checkAnonymousArguments)
       
   123         return;
       
   124 
       
   125     if (_scope->isClassScope() && fun->isPublic()) {
       
   126         for (unsigned argc = 0; argc < fun->argumentCount(); ++argc) {
       
   127             Argument *arg = fun->argumentAt(argc)->asArgument();
       
   128             assert(arg != 0);
       
   129 
       
   130             if (! arg->name()) {
       
   131                 translationUnit()->warning(arg->sourceLocation(),
       
   132                                            "anonymous argument");
       
   133             }
       
   134         }
       
   135     }
       
   136 }
       
   137 
       
   138 unsigned CheckDeclaration::locationOfDeclaratorId(DeclaratorAST *declarator) const
       
   139 {
       
   140     if (declarator && declarator->core_declarator) {
       
   141         if (DeclaratorIdAST *declaratorId = declarator->core_declarator->asDeclaratorId())
       
   142             return declaratorId->firstToken();
       
   143         else if (NestedDeclaratorAST *nested = declarator->core_declarator->asNestedDeclarator())
       
   144             return locationOfDeclaratorId(nested->declarator);
       
   145     }
       
   146 
       
   147     return 0;
       
   148 }
       
   149 
       
   150 bool CheckDeclaration::visit(SimpleDeclarationAST *ast)
       
   151 {
       
   152     FullySpecifiedType ty = semantic()->check(ast->decl_specifier_list, _scope);
       
   153     FullySpecifiedType qualTy = ty.qualifiedType();
       
   154 
       
   155     if (_templateParameters && ty) {
       
   156         if (Class *klass = ty->asClassType()) {
       
   157             klass->setTemplateParameters(_templateParameters);
       
   158         }
       
   159     }
       
   160 
       
   161     if (! ast->declarator_list && ast->decl_specifier_list && ! ast->decl_specifier_list->next) {
       
   162         if (ElaboratedTypeSpecifierAST *elab_type_spec = ast->decl_specifier_list->value->asElaboratedTypeSpecifier()) {
       
   163 
       
   164             unsigned sourceLocation = elab_type_spec->firstToken();
       
   165 
       
   166             if (elab_type_spec->name)
       
   167                 sourceLocation = elab_type_spec->name->firstToken();
       
   168 
       
   169             const Name *name = semantic()->check(elab_type_spec->name, _scope);
       
   170             ForwardClassDeclaration *symbol =
       
   171                     control()->newForwardClassDeclaration(sourceLocation, name);
       
   172 
       
   173             if (_templateParameters) {
       
   174                 symbol->setTemplateParameters(_templateParameters);
       
   175                 _templateParameters = 0;
       
   176             }
       
   177 
       
   178             _scope->enterSymbol(symbol);
       
   179             return false;
       
   180         }
       
   181     }
       
   182 
       
   183     const bool isQ_SLOT   = ast->qt_invokable_token && tokenKind(ast->qt_invokable_token) == T_Q_SLOT;
       
   184     const bool isQ_SIGNAL = ast->qt_invokable_token && tokenKind(ast->qt_invokable_token) == T_Q_SIGNAL;
       
   185 #ifdef ICHECK_BUILD
       
   186     const bool isQ_INVOKABLE = (ast->invoke_token > 0);
       
   187 #endif
       
   188 
       
   189     List<Declaration *> **decl_it = &ast->symbols;
       
   190     for (DeclaratorListAST *it = ast->declarator_list; it; it = it->next) {
       
   191         const Name *name = 0;
       
   192         FullySpecifiedType declTy = semantic()->check(it->value, qualTy,
       
   193                                                       _scope, &name);
       
   194 
       
   195         unsigned location = locationOfDeclaratorId(it->value);
       
   196         if (! location) {
       
   197             if (it->value)
       
   198                 location = it->value->firstToken();
       
   199             else
       
   200                 location = ast->firstToken();
       
   201         }
       
   202 
       
   203         Function *fun = 0;
       
   204         if (declTy && 0 != (fun = declTy->asFunctionType())) {
       
   205             fun->setSourceLocation(location);
       
   206             fun->setScope(_scope);
       
   207             fun->setName(name);
       
   208             fun->setMethodKey(semantic()->currentMethodKey());
       
   209             fun->setVirtual(ty.isVirtual());
       
   210             if (isQ_SIGNAL)
       
   211                 fun->setMethodKey(Function::SignalMethod);
       
   212             else if (isQ_SLOT)
       
   213                 fun->setMethodKey(Function::SlotMethod);
       
   214 #ifdef ICHECK_BUILD
       
   215             else if (isQ_INVOKABLE)
       
   216                 fun->setInvokable(true);
       
   217 #endif
       
   218             fun->setVisibility(semantic()->currentVisibility());
       
   219         } else if (semantic()->currentMethodKey() != Function::NormalMethod) {
       
   220             translationUnit()->warning(ast->firstToken(),
       
   221                                        "expected a function declaration");
       
   222         }
       
   223 
       
   224         Declaration *symbol = control()->newDeclaration(location, name);
       
   225         symbol->setStartOffset(tokenAt(ast->firstToken()).offset);
       
   226         symbol->setEndOffset(tokenAt(ast->lastToken()).offset);
       
   227 
       
   228         symbol->setType(control()->integerType(IntegerType::Int));
       
   229         symbol->setType(declTy);
       
   230 
       
   231         if (_templateParameters && it == ast->declarator_list && ty && ! ty->isClassType())
       
   232             symbol->setTemplateParameters(_templateParameters);
       
   233 
       
   234         symbol->setVisibility(semantic()->currentVisibility());
       
   235 
       
   236         if (ty.isFriend())
       
   237             symbol->setStorage(Symbol::Friend);
       
   238         else if (ty.isRegister())
       
   239             symbol->setStorage(Symbol::Register);
       
   240         else if (ty.isStatic())
       
   241             symbol->setStorage(Symbol::Static);
       
   242         else if (ty.isExtern())
       
   243             symbol->setStorage(Symbol::Extern);
       
   244         else if (ty.isMutable())
       
   245             symbol->setStorage(Symbol::Mutable);
       
   246         else if (ty.isTypedef())
       
   247             symbol->setStorage(Symbol::Typedef);
       
   248 
       
   249         if (it->value && it->value->initializer) {
       
   250             FullySpecifiedType initTy = semantic()->check(it->value->initializer, _scope);
       
   251         }
       
   252 
       
   253         *decl_it = new (translationUnit()->memoryPool()) List<Declaration *>();
       
   254         (*decl_it)->value = symbol;
       
   255         decl_it = &(*decl_it)->next;
       
   256 
       
   257         _scope->enterSymbol(symbol);
       
   258     }
       
   259     return false;
       
   260 }
       
   261 
       
   262 bool CheckDeclaration::visit(EmptyDeclarationAST *)
       
   263 {
       
   264     return false;
       
   265 }
       
   266 
       
   267 bool CheckDeclaration::visit(AccessDeclarationAST *ast)
       
   268 {
       
   269     int accessSpecifier = tokenKind(ast->access_specifier_token);
       
   270     int visibility = semantic()->visibilityForAccessSpecifier(accessSpecifier);
       
   271     semantic()->switchVisibility(visibility);
       
   272     if (ast->slots_token)
       
   273         semantic()->switchMethodKey(Function::SlotMethod);
       
   274     else if (accessSpecifier == T_Q_SIGNALS)
       
   275         semantic()->switchMethodKey(Function::SignalMethod);
       
   276     else
       
   277         semantic()->switchMethodKey(Function::NormalMethod);
       
   278     return false;
       
   279 }
       
   280 
       
   281 #ifdef ICHECK_BUILD
       
   282 bool CheckDeclaration::visit(QPropertyDeclarationAST *)
       
   283 {
       
   284     return false;
       
   285 }
       
   286 
       
   287 bool CheckDeclaration::visit(QEnumDeclarationAST *)
       
   288 {
       
   289     return false;
       
   290 }
       
   291 
       
   292 bool CheckDeclaration::visit(QFlagsDeclarationAST *)
       
   293 {
       
   294     return false;
       
   295 }
       
   296 
       
   297 bool CheckDeclaration::visit(QDeclareFlagsDeclarationAST *)
       
   298 {
       
   299     return false;
       
   300 }
       
   301 #endif
       
   302 
       
   303 bool CheckDeclaration::visit(AsmDefinitionAST *)
       
   304 {
       
   305     return false;
       
   306 }
       
   307 
       
   308 bool CheckDeclaration::visit(ExceptionDeclarationAST *ast)
       
   309 {
       
   310     FullySpecifiedType ty = semantic()->check(ast->type_specifier_list, _scope);
       
   311     FullySpecifiedType qualTy = ty.qualifiedType();
       
   312 
       
   313     const Name *name = 0;
       
   314     FullySpecifiedType declTy = semantic()->check(ast->declarator, qualTy,
       
   315                                                   _scope, &name);
       
   316 
       
   317     unsigned location = locationOfDeclaratorId(ast->declarator);
       
   318     if (! location) {
       
   319         if (ast->declarator)
       
   320             location = ast->declarator->firstToken();
       
   321         else
       
   322             location = ast->firstToken();
       
   323     }
       
   324 
       
   325     Declaration *symbol = control()->newDeclaration(location, name);
       
   326     symbol->setStartOffset(tokenAt(ast->firstToken()).offset);
       
   327     symbol->setEndOffset(tokenAt(ast->lastToken()).offset);
       
   328     symbol->setType(declTy);
       
   329     _scope->enterSymbol(symbol);
       
   330 
       
   331     return false;
       
   332 }
       
   333 
       
   334 bool CheckDeclaration::visit(FunctionDefinitionAST *ast)
       
   335 {
       
   336     FullySpecifiedType ty = semantic()->check(ast->decl_specifier_list, _scope);
       
   337     FullySpecifiedType qualTy = ty.qualifiedType();
       
   338     const Name *name = 0;
       
   339     FullySpecifiedType funTy = semantic()->check(ast->declarator, qualTy,
       
   340                                                  _scope, &name);
       
   341     if (! (funTy && funTy->isFunctionType())) {
       
   342         translationUnit()->error(ast->firstToken(),
       
   343                                  "expected a function prototype");
       
   344         return false;
       
   345     }
       
   346 
       
   347     Function *fun = funTy->asFunctionType();
       
   348     fun->setVirtual(ty.isVirtual());
       
   349     fun->setStartOffset(tokenAt(ast->firstToken()).offset);
       
   350     fun->setEndOffset(tokenAt(ast->lastToken()).offset);
       
   351     if (ast->declarator)
       
   352         fun->setSourceLocation(ast->declarator->firstToken());
       
   353     fun->setName(name);
       
   354     fun->setTemplateParameters(_templateParameters);
       
   355     fun->setVisibility(semantic()->currentVisibility());
       
   356     fun->setMethodKey(semantic()->currentMethodKey());
       
   357 
       
   358     const bool isQ_SLOT   = ast->qt_invokable_token && tokenKind(ast->qt_invokable_token) == T_Q_SLOT;
       
   359     const bool isQ_SIGNAL = ast->qt_invokable_token && tokenKind(ast->qt_invokable_token) == T_Q_SIGNAL;
       
   360 #ifdef ICHECK_BUILD
       
   361     const bool isQ_INVOKABLE = (ast->invoke_token > 0);
       
   362 #endif
       
   363 
       
   364     if (isQ_SIGNAL)
       
   365         fun->setMethodKey(Function::SignalMethod);
       
   366     else if (isQ_SLOT)
       
   367         fun->setMethodKey(Function::SlotMethod);
       
   368 #ifdef ICHECK_BUILD
       
   369     else if (isQ_INVOKABLE)
       
   370         fun->setInvokable(true);
       
   371 #endif
       
   372 
       
   373     checkFunctionArguments(fun);
       
   374 
       
   375     ast->symbol = fun;
       
   376     _scope->enterSymbol(fun);
       
   377 
       
   378     if (! semantic()->skipFunctionBodies()) {
       
   379         if (ast->ctor_initializer) {
       
   380             bool looksLikeCtor = false;
       
   381             if (ty.isValid() || ! fun->identity())
       
   382                 looksLikeCtor = false;
       
   383             else if (fun->identity()->isNameId() || fun->identity()->isTemplateNameId())
       
   384                 looksLikeCtor = true;
       
   385 
       
   386             if (! looksLikeCtor) {
       
   387                 translationUnit()->error(ast->ctor_initializer->firstToken(),
       
   388                                          "only constructors take base initializers");
       
   389             }
       
   390             accept(ast->ctor_initializer);
       
   391         }
       
   392 
       
   393         const int previousVisibility = semantic()->switchVisibility(Symbol::Public);
       
   394         const int previousMethodKey = semantic()->switchMethodKey(Function::NormalMethod);
       
   395 
       
   396         semantic()->check(ast->function_body, fun->members());
       
   397 
       
   398         semantic()->switchMethodKey(previousMethodKey);
       
   399         semantic()->switchVisibility(previousVisibility);
       
   400     }
       
   401 
       
   402     return false;
       
   403 }
       
   404 
       
   405 bool CheckDeclaration::visit(MemInitializerAST *ast)
       
   406 {
       
   407     (void) semantic()->check(ast->name, _scope);
       
   408     for (ExpressionListAST *it = ast->expression_list; it; it = it->next) {
       
   409         FullySpecifiedType ty = semantic()->check(it->value, _scope);
       
   410     }
       
   411     return false;
       
   412 }
       
   413 
       
   414 bool CheckDeclaration::visit(LinkageBodyAST *ast)
       
   415 {
       
   416     for (DeclarationListAST *decl = ast->declaration_list; decl; decl = decl->next) {
       
   417        semantic()->check(decl->value, _scope);
       
   418     }
       
   419     return false;
       
   420 }
       
   421 
       
   422 bool CheckDeclaration::visit(LinkageSpecificationAST *ast)
       
   423 {
       
   424     semantic()->check(ast->declaration, _scope);
       
   425     return false;
       
   426 }
       
   427 
       
   428 bool CheckDeclaration::visit(NamespaceAST *ast)
       
   429 {
       
   430     const Name *namespaceName = 0;
       
   431     if (const Identifier *id = identifier(ast->identifier_token))
       
   432         namespaceName = control()->nameId(id);
       
   433 
       
   434     unsigned sourceLocation = ast->firstToken();
       
   435 
       
   436     if (ast->identifier_token)
       
   437         sourceLocation = ast->identifier_token;
       
   438 
       
   439     Namespace *ns = control()->newNamespace(sourceLocation, namespaceName);
       
   440     ns->setStartOffset(tokenAt(ast->firstToken()).offset);
       
   441     ns->setEndOffset(tokenAt(ast->lastToken()).offset);
       
   442     ast->symbol = ns;
       
   443     _scope->enterSymbol(ns);
       
   444     semantic()->check(ast->linkage_body, ns->members()); // ### we'll do the merge later.
       
   445 
       
   446     return false;
       
   447 }
       
   448 
       
   449 bool CheckDeclaration::visit(NamespaceAliasDefinitionAST *)
       
   450 {
       
   451     return false;
       
   452 }
       
   453 
       
   454 bool CheckDeclaration::visit(ParameterDeclarationAST *ast)
       
   455 {
       
   456     unsigned sourceLocation = locationOfDeclaratorId(ast->declarator);
       
   457     if (! sourceLocation) {
       
   458         if (ast->declarator)
       
   459             sourceLocation = ast->declarator->firstToken();
       
   460         else
       
   461             sourceLocation = ast->firstToken();
       
   462     }
       
   463 
       
   464     const Name *argName = 0;
       
   465     FullySpecifiedType ty = semantic()->check(ast->type_specifier_list, _scope);
       
   466     FullySpecifiedType argTy = semantic()->check(ast->declarator, ty.qualifiedType(),
       
   467                                                  _scope, &argName);
       
   468     FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope);
       
   469     Argument *arg = control()->newArgument(sourceLocation, argName);
       
   470     ast->symbol = arg;
       
   471     if (ast->expression) {
       
   472         unsigned startOfExpression = ast->expression->firstToken();
       
   473         unsigned endOfExpression = ast->expression->lastToken();
       
   474         std::string buffer;
       
   475         for (unsigned index = startOfExpression; index != endOfExpression; ++index) {
       
   476             const Token &tk = tokenAt(index);
       
   477             if (tk.whitespace() || tk.newline())
       
   478                 buffer += ' ';
       
   479             buffer += tk.spell();
       
   480         }
       
   481         const StringLiteral *initializer = control()->findOrInsertStringLiteral(buffer.c_str(), buffer.size());
       
   482         arg->setInitializer(initializer);
       
   483     }
       
   484     arg->setType(argTy);
       
   485     _scope->enterSymbol(arg);
       
   486     return false;
       
   487 }
       
   488 
       
   489 bool CheckDeclaration::visit(TemplateDeclarationAST *ast)
       
   490 {
       
   491     Scope *scope = new Scope(_scope->owner());
       
   492 
       
   493     for (DeclarationListAST *param = ast->template_parameter_list; param; param = param->next) {
       
   494        semantic()->check(param->value, scope);
       
   495     }
       
   496 
       
   497     semantic()->check(ast->declaration, _scope,
       
   498                       new TemplateParameters(_templateParameters, scope));
       
   499 
       
   500     return false;
       
   501 }
       
   502 
       
   503 bool CheckDeclaration::visit(TypenameTypeParameterAST *ast)
       
   504 {
       
   505     unsigned sourceLocation = ast->firstToken();
       
   506     if (ast->name)
       
   507         sourceLocation = ast->name->firstToken();
       
   508 
       
   509     const Name *name = semantic()->check(ast->name, _scope);
       
   510     TypenameArgument *arg = control()->newTypenameArgument(sourceLocation, name);
       
   511     FullySpecifiedType ty = semantic()->check(ast->type_id, _scope);
       
   512     arg->setType(ty);
       
   513     ast->symbol = arg;
       
   514     _scope->enterSymbol(arg);
       
   515     return false;
       
   516 }
       
   517 
       
   518 bool CheckDeclaration::visit(TemplateTypeParameterAST *ast)
       
   519 {
       
   520     unsigned sourceLocation = ast->firstToken();
       
   521     if (ast->name)
       
   522         sourceLocation = ast->name->firstToken();
       
   523 
       
   524     const Name *name = semantic()->check(ast->name, _scope);
       
   525     TypenameArgument *arg = control()->newTypenameArgument(sourceLocation, name);
       
   526     FullySpecifiedType ty = semantic()->check(ast->type_id, _scope);
       
   527     arg->setType(ty);
       
   528     ast->symbol = arg;
       
   529     _scope->enterSymbol(arg);
       
   530     return false;
       
   531 }
       
   532 
       
   533 bool CheckDeclaration::visit(UsingAST *ast)
       
   534 {
       
   535     const Name *name = semantic()->check(ast->name, _scope);
       
   536 
       
   537     unsigned sourceLocation = ast->firstToken();
       
   538     if (ast->name)
       
   539         sourceLocation = ast->name->firstToken();
       
   540 
       
   541     UsingDeclaration *u = control()->newUsingDeclaration(sourceLocation, name);
       
   542     ast->symbol = u;
       
   543     _scope->enterSymbol(u);
       
   544     return false;
       
   545 }
       
   546 
       
   547 bool CheckDeclaration::visit(UsingDirectiveAST *ast)
       
   548 {
       
   549     const Name *name = semantic()->check(ast->name, _scope);
       
   550 
       
   551     unsigned sourceLocation = ast->firstToken();
       
   552     if (ast->name)
       
   553         sourceLocation = ast->name->firstToken();
       
   554 
       
   555     UsingNamespaceDirective *u = control()->newUsingNamespaceDirective(sourceLocation, name);
       
   556     ast->symbol = u;
       
   557     _scope->enterSymbol(u);
       
   558 
       
   559     if (! (_scope->isBlockScope() || _scope->isNamespaceScope()))
       
   560         translationUnit()->error(ast->firstToken(),
       
   561                                  "using-directive not within namespace or block scope");
       
   562 
       
   563     return false;
       
   564 }
       
   565 
       
   566 bool CheckDeclaration::visit(ObjCProtocolForwardDeclarationAST *ast)
       
   567 {
       
   568     const unsigned sourceLocation = ast->firstToken();
       
   569 
       
   570     List<ObjCForwardProtocolDeclaration *> **symbolIter = &ast->symbols;
       
   571     for (ObjCIdentifierListAST *it = ast->identifier_list; it; it = it->next) {
       
   572         unsigned declarationLocation;
       
   573         if (it->value)
       
   574             declarationLocation = it->value->firstToken();
       
   575         else
       
   576             declarationLocation = sourceLocation;
       
   577 
       
   578         const Name *protocolName = semantic()->check(it->value, _scope);
       
   579         ObjCForwardProtocolDeclaration *fwdProtocol = control()->newObjCForwardProtocolDeclaration(sourceLocation, protocolName);
       
   580         fwdProtocol->setStartOffset(tokenAt(ast->firstToken()).offset);
       
   581         fwdProtocol->setEndOffset(tokenAt(ast->lastToken()).offset);
       
   582 
       
   583         _scope->enterSymbol(fwdProtocol);
       
   584 
       
   585         *symbolIter = new (translationUnit()->memoryPool()) List<ObjCForwardProtocolDeclaration *>();
       
   586         (*symbolIter)->value = fwdProtocol;
       
   587         symbolIter = &(*symbolIter)->next;
       
   588     }
       
   589 
       
   590     return false;
       
   591 }
       
   592 
       
   593 bool CheckDeclaration::visit(ObjCProtocolDeclarationAST *ast)
       
   594 {
       
   595     unsigned sourceLocation;
       
   596     if (ast->name)
       
   597         sourceLocation = ast->name->firstToken();
       
   598     else
       
   599         sourceLocation = ast->firstToken();
       
   600 
       
   601     const Name *protocolName = semantic()->check(ast->name, _scope);
       
   602     ObjCProtocol *protocol = control()->newObjCProtocol(sourceLocation, protocolName);
       
   603     protocol->setStartOffset(tokenAt(ast->firstToken()).offset);
       
   604     protocol->setEndOffset(tokenAt(ast->lastToken()).offset);
       
   605 
       
   606     if (ast->protocol_refs && ast->protocol_refs->identifier_list) {
       
   607         for (ObjCIdentifierListAST *iter = ast->protocol_refs->identifier_list; iter; iter = iter->next) {
       
   608             NameAST* name = iter->value;
       
   609             const Name *protocolName = semantic()->check(name, _scope);
       
   610             ObjCBaseProtocol *baseProtocol = control()->newObjCBaseProtocol(name->firstToken(), protocolName);
       
   611             protocol->addProtocol(baseProtocol);
       
   612         }
       
   613     }
       
   614 
       
   615     int previousObjCVisibility = semantic()->switchObjCVisibility(Function::Public);
       
   616     for (DeclarationListAST *it = ast->member_declaration_list; it; it = it->next) {
       
   617         semantic()->check(it->value, protocol->members());
       
   618     }
       
   619     (void) semantic()->switchObjCVisibility(previousObjCVisibility);
       
   620 
       
   621     ast->symbol = protocol;
       
   622     _scope->enterSymbol(protocol);
       
   623 
       
   624     return false;
       
   625 }
       
   626 
       
   627 bool CheckDeclaration::visit(ObjCClassForwardDeclarationAST *ast)
       
   628 {
       
   629     const unsigned sourceLocation = ast->firstToken();
       
   630 
       
   631     List<ObjCForwardClassDeclaration *> **symbolIter = &ast->symbols;
       
   632     for (ObjCIdentifierListAST *it = ast->identifier_list; it; it = it->next) {
       
   633         unsigned declarationLocation;
       
   634         if (it->value)
       
   635             declarationLocation = it->value->firstToken();
       
   636         else
       
   637             declarationLocation = sourceLocation;
       
   638 
       
   639         const Name *className = semantic()->check(it->value, _scope);
       
   640         ObjCForwardClassDeclaration *fwdClass = control()->newObjCForwardClassDeclaration(sourceLocation, className);
       
   641         fwdClass->setStartOffset(tokenAt(ast->firstToken()).offset);
       
   642         fwdClass->setEndOffset(tokenAt(ast->lastToken()).offset);
       
   643 
       
   644         _scope->enterSymbol(fwdClass);
       
   645 
       
   646         *symbolIter = new (translationUnit()->memoryPool()) List<ObjCForwardClassDeclaration *>();
       
   647         (*symbolIter)->value = fwdClass;
       
   648         symbolIter = &(*symbolIter)->next;
       
   649     }
       
   650 
       
   651     return false;
       
   652 }
       
   653 
       
   654 bool CheckDeclaration::visit(ObjCClassDeclarationAST *ast)
       
   655 {
       
   656     unsigned sourceLocation;
       
   657     if (ast->class_name)
       
   658         sourceLocation = ast->class_name->firstToken();
       
   659     else
       
   660         sourceLocation = ast->firstToken();
       
   661 
       
   662     const Name *className = semantic()->check(ast->class_name, _scope);
       
   663     ObjCClass *klass = control()->newObjCClass(sourceLocation, className);
       
   664     klass->setStartOffset(tokenAt(ast->firstToken()).offset);
       
   665     klass->setEndOffset(tokenAt(ast->lastToken()).offset);
       
   666     ast->symbol = klass;
       
   667 
       
   668     klass->setInterface(ast->interface_token != 0);
       
   669 
       
   670     if (ast->category_name) {
       
   671         const Name *categoryName = semantic()->check(ast->category_name, _scope);
       
   672         klass->setCategoryName(categoryName);
       
   673     }
       
   674 
       
   675     if (ast->superclass) {
       
   676         const Name *superClassName = semantic()->check(ast->superclass, _scope);
       
   677         ObjCBaseClass *superKlass = control()->newObjCBaseClass(ast->superclass->firstToken(), superClassName);
       
   678         klass->setBaseClass(superKlass);
       
   679     }
       
   680 
       
   681     if (ast->protocol_refs && ast->protocol_refs->identifier_list) {
       
   682         for (ObjCIdentifierListAST *iter = ast->protocol_refs->identifier_list; iter; iter = iter->next) {
       
   683             NameAST* name = iter->value;
       
   684             const Name *protocolName = semantic()->check(name, _scope);
       
   685             ObjCBaseProtocol *baseProtocol = control()->newObjCBaseProtocol(name->firstToken(), protocolName);
       
   686             klass->addProtocol(baseProtocol);
       
   687         }
       
   688     }
       
   689 
       
   690     _scope->enterSymbol(klass);
       
   691 
       
   692     int previousObjCVisibility = semantic()->switchObjCVisibility(Function::Protected);
       
   693 
       
   694     if (ast->inst_vars_decl) {
       
   695         for (DeclarationListAST *it = ast->inst_vars_decl->instance_variable_list; it; it = it->next) {
       
   696             semantic()->check(it->value, klass->members());
       
   697         }
       
   698     }
       
   699 
       
   700     (void) semantic()->switchObjCVisibility(Function::Public);
       
   701 
       
   702     for (DeclarationListAST *it = ast->member_declaration_list; it; it = it->next) {
       
   703         semantic()->check(it->value, klass->members());
       
   704     }
       
   705 
       
   706     (void) semantic()->switchObjCVisibility(previousObjCVisibility);
       
   707 
       
   708     return false;
       
   709 }
       
   710 
       
   711 bool CheckDeclaration::visit(ObjCMethodDeclarationAST *ast)
       
   712 {
       
   713     if (!ast->method_prototype)
       
   714         return false;
       
   715 
       
   716     FullySpecifiedType ty = semantic()->check(ast->method_prototype, _scope);
       
   717     ObjCMethod *methodTy = ty.type()->asObjCMethodType();
       
   718     if (!methodTy)
       
   719         return false;
       
   720 
       
   721     Symbol *symbol;
       
   722     if (ast->function_body) {
       
   723         if (!semantic()->skipFunctionBodies()) {
       
   724             semantic()->check(ast->function_body, methodTy->members());
       
   725         }
       
   726 
       
   727         symbol = methodTy;
       
   728     } else {
       
   729         Declaration *decl = control()->newDeclaration(ast->firstToken(), methodTy->name());
       
   730         decl->setType(methodTy);
       
   731         symbol = decl;
       
   732         symbol->setStorage(methodTy->storage());
       
   733     }
       
   734 
       
   735     symbol->setStartOffset(tokenAt(ast->firstToken()).offset);
       
   736     symbol->setEndOffset(tokenAt(ast->lastToken()).offset);
       
   737     symbol->setVisibility(semantic()->currentVisibility());
       
   738 
       
   739     _scope->enterSymbol(symbol);
       
   740 
       
   741     return false;
       
   742 }
       
   743 
       
   744 bool CheckDeclaration::visit(ObjCVisibilityDeclarationAST *ast)
       
   745 {
       
   746     int accessSpecifier = tokenKind(ast->visibility_token);
       
   747     int visibility = semantic()->visibilityForObjCAccessSpecifier(accessSpecifier);
       
   748     semantic()->switchObjCVisibility(visibility);
       
   749     return false;
       
   750 }
       
   751 
       
   752 bool CheckDeclaration::checkPropertyAttribute(ObjCPropertyAttributeAST *attrAst,
       
   753                                               int &flags,
       
   754                                               int attr)
       
   755 {
       
   756     if (flags & attr) {
       
   757         translationUnit()->warning(attrAst->attribute_identifier_token,
       
   758                                    "duplicate property attribute \"%s\"",
       
   759                                    spell(attrAst->attribute_identifier_token));
       
   760         return false;
       
   761     } else {
       
   762         flags |= attr;
       
   763         return true;
       
   764     }
       
   765 }
       
   766 
       
   767 bool CheckDeclaration::visit(ObjCPropertyDeclarationAST *ast)
       
   768 {
       
   769     semantic()->check(ast->simple_declaration, _scope);
       
   770     SimpleDeclarationAST *simpleDecl = ast->simple_declaration->asSimpleDeclaration();
       
   771 
       
   772     if (!simpleDecl) {
       
   773         translationUnit()->warning(ast->simple_declaration->firstToken(),
       
   774                                    "invalid type for property declaration");
       
   775         return false;
       
   776     }
       
   777 
       
   778     int propAttrs = ObjCPropertyDeclaration::None;
       
   779     const Name *getterName = 0, *setterName = 0;
       
   780 
       
   781     for (ObjCPropertyAttributeListAST *iter= ast->property_attribute_list; iter; iter = iter->next) {
       
   782         ObjCPropertyAttributeAST *attrAst = iter->value;
       
   783         if (!attrAst)
       
   784             continue;
       
   785 
       
   786         const Identifier *attrId = identifier(attrAst->attribute_identifier_token);
       
   787         if (attrId == control()->objcGetterId()) {
       
   788             if (checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::Getter)) {
       
   789                 getterName = semantic()->check(attrAst->method_selector, _scope);
       
   790             }
       
   791         } else if (attrId == control()->objcSetterId()) {
       
   792             if (checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::Setter)) {
       
   793                 setterName = semantic()->check(attrAst->method_selector, _scope);
       
   794             }
       
   795         } else if (attrId == control()->objcReadwriteId()) {
       
   796             checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::ReadWrite);
       
   797         } else if (attrId == control()->objcReadonlyId()) {
       
   798             checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::ReadOnly);
       
   799         } else if (attrId == control()->objcAssignId()) {
       
   800             checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::Assign);
       
   801         } else if (attrId == control()->objcRetainId()) {
       
   802             checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::Retain);
       
   803         } else if (attrId == control()->objcCopyId()) {
       
   804             checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::Copy);
       
   805         } else if (attrId == control()->objcNonatomicId()) {
       
   806             checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::NonAtomic);
       
   807         }
       
   808     }
       
   809 
       
   810     if (propAttrs & ObjCPropertyDeclaration::ReadOnly &&
       
   811         propAttrs & ObjCPropertyDeclaration::ReadWrite)
       
   812         // Should this be an error instead of only a warning?
       
   813         translationUnit()->warning(ast->property_token,
       
   814                                    "property can have at most one attribute \"readonly\" or \"readwrite\" specified");
       
   815     int setterSemAttrs = propAttrs & ObjCPropertyDeclaration::SetterSemanticsMask;
       
   816     if (setterSemAttrs
       
   817             && setterSemAttrs != ObjCPropertyDeclaration::Assign
       
   818             && setterSemAttrs != ObjCPropertyDeclaration::Retain
       
   819             && setterSemAttrs != ObjCPropertyDeclaration::Copy) {
       
   820         // Should this be an error instead of only a warning?
       
   821         translationUnit()->warning(ast->property_token,
       
   822                                    "property can have at most one attribute \"assign\", \"retain\", or \"copy\" specified");
       
   823     }
       
   824 
       
   825     List<ObjCPropertyDeclaration *> **lastSymbols = &ast->symbols;
       
   826     for (List<Declaration*> *iter = simpleDecl->symbols; iter; iter = iter->next) {
       
   827         ObjCPropertyDeclaration *propDecl = control()->newObjCPropertyDeclaration(ast->firstToken(),
       
   828                                                                                   iter->value->name());
       
   829         propDecl->setType(iter->value->type());
       
   830         propDecl->setAttributes(propAttrs);
       
   831         propDecl->setGetterName(getterName);
       
   832         propDecl->setSetterName(setterName);
       
   833         _scope->enterSymbol(propDecl);
       
   834 
       
   835         *lastSymbols = new (translationUnit()->memoryPool()) List<ObjCPropertyDeclaration *>();
       
   836         (*lastSymbols)->value = propDecl;
       
   837         lastSymbols = &(*lastSymbols)->next;
       
   838     }
       
   839 
       
   840     return false;
       
   841 }