CheckDeclaration.cpp 32.2 KB
Newer Older
1
/**************************************************************************
con's avatar
con committed
2
3
4
**
** This file is part of Qt Creator
**
hjk's avatar
hjk committed
5
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
con's avatar
con committed
6
**
7
** Contact: Nokia Corporation (qt-info@nokia.com)
con's avatar
con committed
8
**
9
** Commercial Usage
10
**
11
12
13
14
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
15
**
16
** GNU Lesser General Public License Usage
17
**
18
19
20
21
22
23
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24
**
25
** If you are unsure which license is appropriate for your use, please
hjk's avatar
hjk committed
26
** contact the sales department at http://qt.nokia.com/contact.
con's avatar
con committed
27
**
28
**************************************************************************/
con's avatar
con committed
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#include "CheckDeclaration.h"
#include "Semantic.h"
#include "AST.h"
#include "TranslationUnit.h"
#include "Scope.h"
#include "Names.h"
#include "CoreTypes.h"
#include "Symbols.h"
#include "Control.h"
58
#include "Literals.h"
59
#include "QtContextKeywords.h"
60
#include <string>
con's avatar
con committed
61
62
#include <cassert>

Roberto Raggi's avatar
Roberto Raggi committed
63
using namespace CPlusPlus;
con's avatar
con committed
64
65
66
67
68
69
70
71
72
73
74
75
76

CheckDeclaration::CheckDeclaration(Semantic *semantic)
    : SemanticCheck(semantic),
      _declaration(0),
      _scope(0),
      _templateParameters(0),
      _checkAnonymousArguments(false)
{ }

CheckDeclaration::~CheckDeclaration()
{ }

void CheckDeclaration::check(DeclarationAST *declaration,
77
                             Scope *scope, TemplateParameters *templateParameters)
con's avatar
con committed
78
79
{
    Scope *previousScope = switchScope(scope);
80
    TemplateParameters *previousTemplateParameters = switchTemplateParameters(templateParameters);
con's avatar
con committed
81
82
83
84
85
86
87
    DeclarationAST *previousDeclaration = switchDeclaration(declaration);
    accept(declaration);
    (void) switchDeclaration(previousDeclaration);
    (void) switchTemplateParameters(previousTemplateParameters);
    (void) switchScope(previousScope);
}

88
89
90
91
92
93
94
void CheckDeclaration::check(CtorInitializerAST *ast, Scope *scope)
{
    Scope *previousScope = switchScope(scope);
    accept(ast);
    (void) switchScope(previousScope);
}

con's avatar
con committed
95
96
97
98
99
100
101
102
103
104
105
106
107
108
DeclarationAST *CheckDeclaration::switchDeclaration(DeclarationAST *declaration)
{
    DeclarationAST *previousDeclaration = _declaration;
    _declaration = declaration;
    return previousDeclaration;
}

Scope *CheckDeclaration::switchScope(Scope *scope)
{
    Scope *previousScope = _scope;
    _scope = scope;
    return previousScope;
}

109
TemplateParameters *CheckDeclaration::switchTemplateParameters(TemplateParameters *templateParameters)
con's avatar
con committed
110
{
111
    TemplateParameters *previousTemplateParameters = _templateParameters;
con's avatar
con committed
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
    _templateParameters = templateParameters;
    return previousTemplateParameters;
}

void CheckDeclaration::checkFunctionArguments(Function *fun)
{
    if (! _checkAnonymousArguments)
        return;

    if (_scope->isClassScope() && fun->isPublic()) {
        for (unsigned argc = 0; argc < fun->argumentCount(); ++argc) {
            Argument *arg = fun->argumentAt(argc)->asArgument();
            assert(arg != 0);

            if (! arg->name()) {
                translationUnit()->warning(arg->sourceLocation(),
                                           "anonymous argument");
            }
        }
    }
}

134
135
136
137
138
139
140
141
142
143
144
145
unsigned CheckDeclaration::locationOfDeclaratorId(DeclaratorAST *declarator) const
{
    if (declarator && declarator->core_declarator) {
        if (DeclaratorIdAST *declaratorId = declarator->core_declarator->asDeclaratorId())
            return declaratorId->firstToken();
        else if (NestedDeclaratorAST *nested = declarator->core_declarator->asNestedDeclarator())
            return locationOfDeclaratorId(nested->declarator);
    }

    return 0;
}

con's avatar
con committed
146
147
bool CheckDeclaration::visit(SimpleDeclarationAST *ast)
{
Roberto Raggi's avatar
Roberto Raggi committed
148
    FullySpecifiedType ty = semantic()->check(ast->decl_specifier_list, _scope);
con's avatar
con committed
149
150
    FullySpecifiedType qualTy = ty.qualifiedType();

151
152
    if (_templateParameters && ty) {
        if (Class *klass = ty->asClassType()) {
con's avatar
con committed
153
            klass->setTemplateParameters(_templateParameters);
154
            _templateParameters = 0; // consume the template parameters
con's avatar
con committed
155
156
157
        }
    }

158
159
    if (ast->decl_specifier_list && ! ast->declarator_list) {
        ElaboratedTypeSpecifierAST *elab_type_spec = ast->decl_specifier_list->value->asElaboratedTypeSpecifier();
160

161
162
163
164
        if (! elab_type_spec && ty.isFriend() && ast->decl_specifier_list->next && ! ast->decl_specifier_list->next->next) {
            // friend template class
            elab_type_spec = ast->decl_specifier_list->next->value->asElaboratedTypeSpecifier();
        }
165

166
167
        if (elab_type_spec) {
            unsigned sourceLocation = ast->decl_specifier_list->firstToken();
168

Roberto Raggi's avatar
Roberto Raggi committed
169
            const Name *name = semantic()->check(elab_type_spec->name, _scope);
170
            ForwardClassDeclaration *symbol =
171
                    control()->newForwardClassDeclaration(sourceLocation, name);
172
173
174
175
176

            if (_templateParameters) {
                symbol->setTemplateParameters(_templateParameters);
                _templateParameters = 0;
            }
177
178
            if (ty.isDeprecated())
                symbol->setDeprecated(true);
179
180
181
182
183
184

            _scope->enterSymbol(symbol);
            return false;
        }
    }

185
186
    const bool isQ_SLOT   = ast->qt_invokable_token && tokenKind(ast->qt_invokable_token) == T_Q_SLOT;
    const bool isQ_SIGNAL = ast->qt_invokable_token && tokenKind(ast->qt_invokable_token) == T_Q_SIGNAL;
187
    const bool isQ_INVOKABLE = ast->qt_invokable_token && tokenKind(ast->qt_invokable_token) == T_Q_INVOKABLE;
188

Roberto Raggi's avatar
Roberto Raggi committed
189
    List<Declaration *> **decl_it = &ast->symbols;
Roberto Raggi's avatar
Roberto Raggi committed
190
    for (DeclaratorListAST *it = ast->declarator_list; it; it = it->next) {
Roberto Raggi's avatar
Roberto Raggi committed
191
        const Name *name = 0;
Roberto Raggi's avatar
Roberto Raggi committed
192
        FullySpecifiedType declTy = semantic()->check(it->value, qualTy,
con's avatar
con committed
193
194
                                                      _scope, &name);

Roberto Raggi's avatar
Roberto Raggi committed
195
        unsigned location = locationOfDeclaratorId(it->value);
196
        if (! location) {
Roberto Raggi's avatar
Roberto Raggi committed
197
198
            if (it->value)
                location = it->value->firstToken();
199
200
201
            else
                location = ast->firstToken();
        }
202

203
204
        Function *fun = 0;
        if (declTy && 0 != (fun = declTy->asFunctionType())) {
205
            fun->setSourceLocation(location);
con's avatar
con committed
206
207
208
            fun->setScope(_scope);
            fun->setName(name);
            fun->setMethodKey(semantic()->currentMethodKey());
209
            fun->setVirtual(ty.isVirtual());
210
211
            if (ty.isDeprecated())
                fun->setDeprecated(true);
212
213
214
215
            if (isQ_SIGNAL)
                fun->setMethodKey(Function::SignalMethod);
            else if (isQ_SLOT)
                fun->setMethodKey(Function::SlotMethod);
216
            else if (isQ_INVOKABLE)
217
                fun->setMethodKey(Function::InvokableMethod);
con's avatar
con committed
218
219
220
221
222
223
224
            fun->setVisibility(semantic()->currentVisibility());
        } else if (semantic()->currentMethodKey() != Function::NormalMethod) {
            translationUnit()->warning(ast->firstToken(),
                                       "expected a function declaration");
        }

        Declaration *symbol = control()->newDeclaration(location, name);
225
226
227
        symbol->setStartOffset(tokenAt(ast->firstToken()).offset);
        symbol->setEndOffset(tokenAt(ast->lastToken()).offset);

con's avatar
con committed
228
        symbol->setType(declTy);
229
230
        if (declTy.isDeprecated())
            symbol->setDeprecated(true);
con's avatar
con committed
231

232
        if (_templateParameters && it == ast->declarator_list) {
con's avatar
con committed
233
            symbol->setTemplateParameters(_templateParameters);
234
235
            _templateParameters = 0; // consume the template parameters
        }
con's avatar
con committed
236
237
238
239
240

        symbol->setVisibility(semantic()->currentVisibility());

        if (ty.isFriend())
            symbol->setStorage(Symbol::Friend);
241
242
        else if (ty.isAuto())
            symbol->setStorage(Symbol::Auto);
con's avatar
con committed
243
244
245
246
247
248
249
250
251
252
        else if (ty.isRegister())
            symbol->setStorage(Symbol::Register);
        else if (ty.isStatic())
            symbol->setStorage(Symbol::Static);
        else if (ty.isExtern())
            symbol->setStorage(Symbol::Extern);
        else if (ty.isMutable())
            symbol->setStorage(Symbol::Mutable);
        else if (ty.isTypedef())
            symbol->setStorage(Symbol::Typedef);
253
254

        if (ty.isDeprecated())
255
            symbol->setDeprecated(true);
con's avatar
con committed
256

Roberto Raggi's avatar
Roberto Raggi committed
257
258
        if (it->value && it->value->initializer) {
            FullySpecifiedType initTy = semantic()->check(it->value->initializer, _scope);
259
260
        }

Roberto Raggi's avatar
Roberto Raggi committed
261
262
263
264
        *decl_it = new (translationUnit()->memoryPool()) List<Declaration *>();
        (*decl_it)->value = symbol;
        decl_it = &(*decl_it)->next;

con's avatar
con committed
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
        _scope->enterSymbol(symbol);
    }
    return false;
}

bool CheckDeclaration::visit(EmptyDeclarationAST *)
{
    return false;
}

bool CheckDeclaration::visit(AccessDeclarationAST *ast)
{
    int accessSpecifier = tokenKind(ast->access_specifier_token);
    int visibility = semantic()->visibilityForAccessSpecifier(accessSpecifier);
    semantic()->switchVisibility(visibility);
    if (ast->slots_token)
        semantic()->switchMethodKey(Function::SlotMethod);
282
    else if (accessSpecifier == T_Q_SIGNALS)
con's avatar
con committed
283
284
285
286
287
288
289
290
291
292
293
        semantic()->switchMethodKey(Function::SignalMethod);
    else
        semantic()->switchMethodKey(Function::NormalMethod);
    return false;
}

bool CheckDeclaration::visit(AsmDefinitionAST *)
{
    return false;
}

294
bool CheckDeclaration::visit(ExceptionDeclarationAST *ast)
con's avatar
con committed
295
{
Roberto Raggi's avatar
Roberto Raggi committed
296
    FullySpecifiedType ty = semantic()->check(ast->type_specifier_list, _scope);
297
298
    FullySpecifiedType qualTy = ty.qualifiedType();

Roberto Raggi's avatar
Roberto Raggi committed
299
    const Name *name = 0;
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
    FullySpecifiedType declTy = semantic()->check(ast->declarator, qualTy,
                                                  _scope, &name);

    unsigned location = locationOfDeclaratorId(ast->declarator);
    if (! location) {
        if (ast->declarator)
            location = ast->declarator->firstToken();
        else
            location = ast->firstToken();
    }

    Declaration *symbol = control()->newDeclaration(location, name);
    symbol->setStartOffset(tokenAt(ast->firstToken()).offset);
    symbol->setEndOffset(tokenAt(ast->lastToken()).offset);
    symbol->setType(declTy);
    _scope->enterSymbol(symbol);

con's avatar
con committed
317
318
319
320
321
    return false;
}

bool CheckDeclaration::visit(FunctionDefinitionAST *ast)
{
Roberto Raggi's avatar
Roberto Raggi committed
322
    FullySpecifiedType ty = semantic()->check(ast->decl_specifier_list, _scope);
con's avatar
con committed
323
    FullySpecifiedType qualTy = ty.qualifiedType();
Roberto Raggi's avatar
Roberto Raggi committed
324
    const Name *name = 0;
con's avatar
con committed
325
326
    FullySpecifiedType funTy = semantic()->check(ast->declarator, qualTy,
                                                 _scope, &name);
327
    if (! (funTy && funTy->isFunctionType())) {
con's avatar
con committed
328
329
330
331
332
        translationUnit()->error(ast->firstToken(),
                                 "expected a function prototype");
        return false;
    }

333
    Function *fun = funTy->asFunctionType();
334
    fun->setVirtual(ty.isVirtual());
335
336
    if (ty.isDeprecated())
        fun->setDeprecated(true);
337
338
    fun->setStartOffset(tokenAt(ast->firstToken()).offset);
    fun->setEndOffset(tokenAt(ast->lastToken()).offset);
339
340
    if (ast->declarator)
        fun->setSourceLocation(ast->declarator->firstToken());
con's avatar
con committed
341
342
343
344
345
    fun->setName(name);
    fun->setTemplateParameters(_templateParameters);
    fun->setVisibility(semantic()->currentVisibility());
    fun->setMethodKey(semantic()->currentMethodKey());

346
347
    const bool isQ_SLOT   = ast->qt_invokable_token && tokenKind(ast->qt_invokable_token) == T_Q_SLOT;
    const bool isQ_SIGNAL = ast->qt_invokable_token && tokenKind(ast->qt_invokable_token) == T_Q_SIGNAL;
348
    const bool isQ_INVOKABLE = ast->qt_invokable_token && tokenKind(ast->qt_invokable_token) == T_Q_INVOKABLE;
349
350
351
352
353

    if (isQ_SIGNAL)
        fun->setMethodKey(Function::SignalMethod);
    else if (isQ_SLOT)
        fun->setMethodKey(Function::SlotMethod);
354
    else if (isQ_INVOKABLE)
355
        fun->setMethodKey(Function::InvokableMethod);
356

con's avatar
con committed
357
358
    checkFunctionArguments(fun);

Roberto Raggi's avatar
Roberto Raggi committed
359
    ast->symbol = fun;
con's avatar
con committed
360
361
    _scope->enterSymbol(fun);

362
363
    if (! semantic()->skipFunctionBodies())
        semantic()->checkFunctionDefinition(ast);
con's avatar
con committed
364
365
366
367

    return false;
}

Roberto Raggi's avatar
Roberto Raggi committed
368
369
370
bool CheckDeclaration::visit(MemInitializerAST *ast)
{
    (void) semantic()->check(ast->name, _scope);
371
372
373
    for (ExpressionListAST *it = ast->expression_list; it; it = it->next) {
        FullySpecifiedType ty = semantic()->check(it->value, _scope);
    }
Roberto Raggi's avatar
Roberto Raggi committed
374
375
376
    return false;
}

con's avatar
con committed
377
378
bool CheckDeclaration::visit(LinkageBodyAST *ast)
{
Roberto Raggi's avatar
Roberto Raggi committed
379
    for (DeclarationListAST *decl = ast->declaration_list; decl; decl = decl->next) {
380
       semantic()->check(decl->value, _scope);
con's avatar
con committed
381
382
383
384
385
386
    }
    return false;
}

bool CheckDeclaration::visit(LinkageSpecificationAST *ast)
{
Roberto Raggi's avatar
Roberto Raggi committed
387
    semantic()->check(ast->declaration, _scope);
con's avatar
con committed
388
389
390
391
392
    return false;
}

bool CheckDeclaration::visit(NamespaceAST *ast)
{
Roberto Raggi's avatar
Roberto Raggi committed
393
394
395
    const Name *namespaceName = 0;
    if (const Identifier *id = identifier(ast->identifier_token))
        namespaceName = control()->nameId(id);
396
397
398
399
400
401
402

    unsigned sourceLocation = ast->firstToken();

    if (ast->identifier_token)
        sourceLocation = ast->identifier_token;

    Namespace *ns = control()->newNamespace(sourceLocation, namespaceName);
403
404
    ns->setStartOffset(tokenAt(ast->firstToken()).offset);
    ns->setEndOffset(tokenAt(ast->lastToken()).offset);
Roberto Raggi's avatar
Roberto Raggi committed
405
    ast->symbol = ns;
con's avatar
con committed
406
407
408
409
410
411
    _scope->enterSymbol(ns);
    semantic()->check(ast->linkage_body, ns->members()); // ### we'll do the merge later.

    return false;
}

412
bool CheckDeclaration::visit(NamespaceAliasDefinitionAST *ast)
con's avatar
con committed
413
{
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
    const Name *name = 0;

    if (const Identifier *id = identifier(ast->namespace_name_token))
        name = control()->nameId(id);

    unsigned sourceLocation = ast->firstToken();

    if (ast->namespace_name_token)
        sourceLocation = ast->namespace_name_token;

    const Name *namespaceName = semantic()->check(ast->name, _scope);

    NamespaceAlias *namespaceAlias = control()->newNamespaceAlias(sourceLocation, name);
    namespaceAlias->setNamespaceName(namespaceName);
    namespaceAlias->setStartOffset(tokenAt(ast->firstToken()).offset);
    namespaceAlias->setEndOffset(tokenAt(ast->lastToken()).offset);
    //ast->symbol = namespaceAlias;
    _scope->enterSymbol(namespaceAlias);

con's avatar
con committed
433
434
435
436
437
    return false;
}

bool CheckDeclaration::visit(ParameterDeclarationAST *ast)
{
438
439
440
441
442
443
444
    unsigned sourceLocation = locationOfDeclaratorId(ast->declarator);
    if (! sourceLocation) {
        if (ast->declarator)
            sourceLocation = ast->declarator->firstToken();
        else
            sourceLocation = ast->firstToken();
    }
445

Roberto Raggi's avatar
Roberto Raggi committed
446
    const Name *argName = 0;
Roberto Raggi's avatar
Roberto Raggi committed
447
    FullySpecifiedType ty = semantic()->check(ast->type_specifier_list, _scope);
con's avatar
con committed
448
449
450
    FullySpecifiedType argTy = semantic()->check(ast->declarator, ty.qualifiedType(),
                                                 _scope, &argName);
    FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope);
451
    Argument *arg = control()->newArgument(sourceLocation, argName);
Roberto Raggi's avatar
Roberto Raggi committed
452
    ast->symbol = arg;
453
454
455
456
457
458
459
460
461
462
463
464
465
    if (ast->expression) {
        unsigned startOfExpression = ast->expression->firstToken();
        unsigned endOfExpression = ast->expression->lastToken();
        std::string buffer;
        for (unsigned index = startOfExpression; index != endOfExpression; ++index) {
            const Token &tk = tokenAt(index);
            if (tk.whitespace() || tk.newline())
                buffer += ' ';
            buffer += tk.spell();
        }
        const StringLiteral *initializer = control()->findOrInsertStringLiteral(buffer.c_str(), buffer.size());
        arg->setInitializer(initializer);
    }
con's avatar
con committed
466
467
468
469
470
471
472
    arg->setType(argTy);
    _scope->enterSymbol(arg);
    return false;
}

bool CheckDeclaration::visit(TemplateDeclarationAST *ast)
{
473
474
    Scope *scope = new Scope(_scope->owner());

Roberto Raggi's avatar
Roberto Raggi committed
475
    for (DeclarationListAST *param = ast->template_parameter_list; param; param = param->next) {
476
       semantic()->check(param->value, scope);
con's avatar
con committed
477
478
    }

479
480
481
    semantic()->check(ast->declaration, _scope,
                      new TemplateParameters(_templateParameters, scope));

con's avatar
con committed
482
483
484
485
486
    return false;
}

bool CheckDeclaration::visit(TypenameTypeParameterAST *ast)
{
487
488
489
490
    unsigned sourceLocation = ast->firstToken();
    if (ast->name)
        sourceLocation = ast->name->firstToken();

Roberto Raggi's avatar
Roberto Raggi committed
491
    const Name *name = semantic()->check(ast->name, _scope);
492
493
494
    TypenameArgument *arg = control()->newTypenameArgument(sourceLocation, name);
    FullySpecifiedType ty = semantic()->check(ast->type_id, _scope);
    arg->setType(ty);
Roberto Raggi's avatar
Roberto Raggi committed
495
    ast->symbol = arg;
con's avatar
con committed
496
497
498
499
500
501
    _scope->enterSymbol(arg);
    return false;
}

bool CheckDeclaration::visit(TemplateTypeParameterAST *ast)
{
502
503
504
505
    unsigned sourceLocation = ast->firstToken();
    if (ast->name)
        sourceLocation = ast->name->firstToken();

Roberto Raggi's avatar
Roberto Raggi committed
506
    const Name *name = semantic()->check(ast->name, _scope);
507
508
509
    TypenameArgument *arg = control()->newTypenameArgument(sourceLocation, name);
    FullySpecifiedType ty = semantic()->check(ast->type_id, _scope);
    arg->setType(ty);
Roberto Raggi's avatar
Roberto Raggi committed
510
    ast->symbol = arg;
con's avatar
con committed
511
512
513
514
515
516
    _scope->enterSymbol(arg);
    return false;
}

bool CheckDeclaration::visit(UsingAST *ast)
{
Roberto Raggi's avatar
Roberto Raggi committed
517
    const Name *name = semantic()->check(ast->name, _scope);
518
519
520
521
522
523

    unsigned sourceLocation = ast->firstToken();
    if (ast->name)
        sourceLocation = ast->name->firstToken();

    UsingDeclaration *u = control()->newUsingDeclaration(sourceLocation, name);
Roberto Raggi's avatar
Roberto Raggi committed
524
    ast->symbol = u;
con's avatar
con committed
525
526
527
528
529
530
    _scope->enterSymbol(u);
    return false;
}

bool CheckDeclaration::visit(UsingDirectiveAST *ast)
{
Roberto Raggi's avatar
Roberto Raggi committed
531
    const Name *name = semantic()->check(ast->name, _scope);
532
533
534
535
536
537

    unsigned sourceLocation = ast->firstToken();
    if (ast->name)
        sourceLocation = ast->name->firstToken();

    UsingNamespaceDirective *u = control()->newUsingNamespaceDirective(sourceLocation, name);
Roberto Raggi's avatar
Roberto Raggi committed
538
    ast->symbol = u;
con's avatar
con committed
539
    _scope->enterSymbol(u);
540
541
542
543
544

    if (! (_scope->isBlockScope() || _scope->isNamespaceScope()))
        translationUnit()->error(ast->firstToken(),
                                 "using-directive not within namespace or block scope");

con's avatar
con committed
545
546
547
    return false;
}

Erik Verbruggen's avatar
Erik Verbruggen committed
548
bool CheckDeclaration::visit(ObjCProtocolForwardDeclarationAST *ast)
549
550
551
552
{
    const unsigned sourceLocation = ast->firstToken();

    List<ObjCForwardProtocolDeclaration *> **symbolIter = &ast->symbols;
553
    for (NameListAST *it = ast->identifier_list; it; it = it->next) {
554
        unsigned declarationLocation;
Roberto Raggi's avatar
Roberto Raggi committed
555
556
        if (it->value)
            declarationLocation = it->value->firstToken();
557
558
559
        else
            declarationLocation = sourceLocation;

Roberto Raggi's avatar
Roberto Raggi committed
560
        const Name *protocolName = semantic()->check(it->value, _scope);
561
562
563
564
565
566
567
568
569
570
571
572
573
574
        ObjCForwardProtocolDeclaration *fwdProtocol = control()->newObjCForwardProtocolDeclaration(sourceLocation, protocolName);
        fwdProtocol->setStartOffset(tokenAt(ast->firstToken()).offset);
        fwdProtocol->setEndOffset(tokenAt(ast->lastToken()).offset);

        _scope->enterSymbol(fwdProtocol);

        *symbolIter = new (translationUnit()->memoryPool()) List<ObjCForwardProtocolDeclaration *>();
        (*symbolIter)->value = fwdProtocol;
        symbolIter = &(*symbolIter)->next;
    }

    return false;
}

Erik Verbruggen's avatar
Erik Verbruggen committed
575
bool CheckDeclaration::visit(ObjCProtocolDeclarationAST *ast)
576
577
578
579
580
581
582
{
    unsigned sourceLocation;
    if (ast->name)
        sourceLocation = ast->name->firstToken();
    else
        sourceLocation = ast->firstToken();

Roberto Raggi's avatar
Roberto Raggi committed
583
    const Name *protocolName = semantic()->check(ast->name, _scope);
584
585
586
587
    ObjCProtocol *protocol = control()->newObjCProtocol(sourceLocation, protocolName);
    protocol->setStartOffset(tokenAt(ast->firstToken()).offset);
    protocol->setEndOffset(tokenAt(ast->lastToken()).offset);

588
    if (ast->protocol_refs && ast->protocol_refs->identifier_list) {
589
        for (NameListAST *iter = ast->protocol_refs->identifier_list; iter; iter = iter->next) {
Roberto Raggi's avatar
Roberto Raggi committed
590
            NameAST* name = iter->value;
Roberto Raggi's avatar
Roberto Raggi committed
591
            const Name *protocolName = semantic()->check(name, _scope);
592
593
594
595
596
597
            ObjCBaseProtocol *baseProtocol = control()->newObjCBaseProtocol(name->firstToken(), protocolName);
            protocol->addProtocol(baseProtocol);
        }
    }

    int previousObjCVisibility = semantic()->switchObjCVisibility(Function::Public);
Roberto Raggi's avatar
Roberto Raggi committed
598
    for (DeclarationListAST *it = ast->member_declaration_list; it; it = it->next) {
599
        semantic()->check(it->value, protocol->members());
600
601
602
603
    }
    (void) semantic()->switchObjCVisibility(previousObjCVisibility);

    ast->symbol = protocol;
604
605
606
607
608
    _scope->enterSymbol(protocol);

    return false;
}

Erik Verbruggen's avatar
Erik Verbruggen committed
609
bool CheckDeclaration::visit(ObjCClassForwardDeclarationAST *ast)
610
611
612
613
{
    const unsigned sourceLocation = ast->firstToken();

    List<ObjCForwardClassDeclaration *> **symbolIter = &ast->symbols;
614
    for (NameListAST *it = ast->identifier_list; it; it = it->next) {
615
        unsigned declarationLocation;
Roberto Raggi's avatar
Roberto Raggi committed
616
617
        if (it->value)
            declarationLocation = it->value->firstToken();
618
619
620
        else
            declarationLocation = sourceLocation;

Roberto Raggi's avatar
Roberto Raggi committed
621
        const Name *className = semantic()->check(it->value, _scope);
622
623
624
625
626
627
628
629
630
631
632
633
634
635
        ObjCForwardClassDeclaration *fwdClass = control()->newObjCForwardClassDeclaration(sourceLocation, className);
        fwdClass->setStartOffset(tokenAt(ast->firstToken()).offset);
        fwdClass->setEndOffset(tokenAt(ast->lastToken()).offset);

        _scope->enterSymbol(fwdClass);

        *symbolIter = new (translationUnit()->memoryPool()) List<ObjCForwardClassDeclaration *>();
        (*symbolIter)->value = fwdClass;
        symbolIter = &(*symbolIter)->next;
    }

    return false;
}

Erik Verbruggen's avatar
Erik Verbruggen committed
636
bool CheckDeclaration::visit(ObjCClassDeclarationAST *ast)
637
638
639
640
641
642
643
{
    unsigned sourceLocation;
    if (ast->class_name)
        sourceLocation = ast->class_name->firstToken();
    else
        sourceLocation = ast->firstToken();

Roberto Raggi's avatar
Roberto Raggi committed
644
    const Name *className = semantic()->check(ast->class_name, _scope);
645
646
647
648
649
    ObjCClass *klass = control()->newObjCClass(sourceLocation, className);
    klass->setStartOffset(tokenAt(ast->firstToken()).offset);
    klass->setEndOffset(tokenAt(ast->lastToken()).offset);
    ast->symbol = klass;

650
651
652
    klass->setInterface(ast->interface_token != 0);

    if (ast->category_name) {
Roberto Raggi's avatar
Roberto Raggi committed
653
        const Name *categoryName = semantic()->check(ast->category_name, _scope);
654
655
656
        klass->setCategoryName(categoryName);
    }

657
    if (ast->superclass) {
Roberto Raggi's avatar
Roberto Raggi committed
658
        const Name *superClassName = semantic()->check(ast->superclass, _scope);
659
660
661
662
663
        ObjCBaseClass *superKlass = control()->newObjCBaseClass(ast->superclass->firstToken(), superClassName);
        klass->setBaseClass(superKlass);
    }

    if (ast->protocol_refs && ast->protocol_refs->identifier_list) {
664
        for (NameListAST *iter = ast->protocol_refs->identifier_list; iter; iter = iter->next) {
Roberto Raggi's avatar
Roberto Raggi committed
665
            NameAST* name = iter->value;
Roberto Raggi's avatar
Roberto Raggi committed
666
            const Name *protocolName = semantic()->check(name, _scope);
667
668
669
670
671
            ObjCBaseProtocol *baseProtocol = control()->newObjCBaseProtocol(name->firstToken(), protocolName);
            klass->addProtocol(baseProtocol);
        }
    }

672
673
674
675
676
    _scope->enterSymbol(klass);

    int previousObjCVisibility = semantic()->switchObjCVisibility(Function::Protected);

    if (ast->inst_vars_decl) {
Roberto Raggi's avatar
Roberto Raggi committed
677
        for (DeclarationListAST *it = ast->inst_vars_decl->instance_variable_list; it; it = it->next) {
678
            semantic()->check(it->value, klass->members());
679
680
681
        }
    }

Erik Verbruggen's avatar
Erik Verbruggen committed
682
683
    (void) semantic()->switchObjCVisibility(Function::Public);

Roberto Raggi's avatar
Roberto Raggi committed
684
    for (DeclarationListAST *it = ast->member_declaration_list; it; it = it->next) {
685
        semantic()->check(it->value, klass->members());
686
687
688
689
690
691
692
693
694
    }

    (void) semantic()->switchObjCVisibility(previousObjCVisibility);

    return false;
}

bool CheckDeclaration::visit(ObjCMethodDeclarationAST *ast)
{
695
696
697
698
699
    ObjCMethodPrototypeAST *methodProto = ast->method_prototype;
    if (!methodProto)
        return false;
    ObjCSelectorAST *selector = methodProto->selector;
    if (!selector)
700
701
        return false;

702
    FullySpecifiedType ty = semantic()->check(methodProto, _scope);
703
704
    ObjCMethod *methodTy = ty.type()->asObjCMethodType();
    if (!methodTy)
705
706
        return false;

707
    Symbol *symbol;
Erik Verbruggen's avatar
Erik Verbruggen committed
708
    if (ast->function_body) {
709
        if (!semantic()->skipFunctionBodies()) {
710
            semantic()->check(ast->function_body, methodTy->members());
711
        }
712

713
        symbol = methodTy;
Erik Verbruggen's avatar
Erik Verbruggen committed
714
    } else {
715
        Declaration *decl = control()->newDeclaration(selector->firstToken(), methodTy->name());
716
        decl->setType(methodTy);
Erik Verbruggen's avatar
Erik Verbruggen committed
717
        symbol = decl;
718
        symbol->setStorage(methodTy->storage());
719
    }
720

721
722
    symbol->setStartOffset(tokenAt(ast->firstToken()).offset);
    symbol->setEndOffset(tokenAt(ast->lastToken()).offset);
723
    symbol->setVisibility(semantic()->currentObjCVisibility());
724
725
    if (ty.isDeprecated())
        symbol->setDeprecated(true);
726
727
728

    _scope->enterSymbol(symbol);

729
730
731
    return false;
}

732
733
734
735
736
737
738
739
bool CheckDeclaration::visit(ObjCVisibilityDeclarationAST *ast)
{
    int accessSpecifier = tokenKind(ast->visibility_token);
    int visibility = semantic()->visibilityForObjCAccessSpecifier(accessSpecifier);
    semantic()->switchObjCVisibility(visibility);
    return false;
}

740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
bool CheckDeclaration::checkPropertyAttribute(ObjCPropertyAttributeAST *attrAst,
                                              int &flags,
                                              int attr)
{
    if (flags & attr) {
        translationUnit()->warning(attrAst->attribute_identifier_token,
                                   "duplicate property attribute \"%s\"",
                                   spell(attrAst->attribute_identifier_token));
        return false;
    } else {
        flags |= attr;
        return true;
    }
}

bool CheckDeclaration::visit(ObjCPropertyDeclarationAST *ast)
{
757
758
759
760
761
762
763
764
765
766
    semantic()->check(ast->simple_declaration, _scope);
    SimpleDeclarationAST *simpleDecl = ast->simple_declaration->asSimpleDeclaration();

    if (!simpleDecl) {
        translationUnit()->warning(ast->simple_declaration->firstToken(),
                                   "invalid type for property declaration");
        return false;
    }

    int propAttrs = ObjCPropertyDeclaration::None;
Roberto Raggi's avatar
Roberto Raggi committed
767
    const Name *getterName = 0, *setterName = 0;
768

Roberto Raggi's avatar
Roberto Raggi committed
769
    for (ObjCPropertyAttributeListAST *iter= ast->property_attribute_list; iter; iter = iter->next) {
770
        ObjCPropertyAttributeAST *attrAst = iter->value;
771
772
773
        if (!attrAst)
            continue;

Roberto Raggi's avatar
Roberto Raggi committed
774
        const Identifier *attrId = identifier(attrAst->attribute_identifier_token);
775
        if (attrId == control()->objcGetterId()) {
776
777
            if (checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::Getter)) {
                getterName = semantic()->check(attrAst->method_selector, _scope);
778
            }
779
        } else if (attrId == control()->objcSetterId()) {
780
781
            if (checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::Setter)) {
                setterName = semantic()->check(attrAst->method_selector, _scope);
782
            }
783
        } else if (attrId == control()->objcReadwriteId()) {
784
            checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::ReadWrite);
785
        } else if (attrId == control()->objcReadonlyId()) {
786
            checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::ReadOnly);
787
        } else if (attrId == control()->objcAssignId()) {
788
            checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::Assign);
789
        } else if (attrId == control()->objcRetainId()) {
790
            checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::Retain);
791
        } else if (attrId == control()->objcCopyId()) {
792
            checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::Copy);
793
        } else if (attrId == control()->objcNonatomicId()) {
794
            checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::NonAtomic);
795
796
797
        }
    }

798
799
    if (propAttrs & ObjCPropertyDeclaration::ReadOnly &&
        propAttrs & ObjCPropertyDeclaration::ReadWrite)
800
801
802
        // Should this be an error instead of only a warning?
        translationUnit()->warning(ast->property_token,
                                   "property can have at most one attribute \"readonly\" or \"readwrite\" specified");
803
    int setterSemAttrs = propAttrs & ObjCPropertyDeclaration::SetterSemanticsMask;
804
    if (setterSemAttrs
805
806
807
            && setterSemAttrs != ObjCPropertyDeclaration::Assign
            && setterSemAttrs != ObjCPropertyDeclaration::Retain
            && setterSemAttrs != ObjCPropertyDeclaration::Copy) {
808
809
810
811
812
        // Should this be an error instead of only a warning?
        translationUnit()->warning(ast->property_token,
                                   "property can have at most one attribute \"assign\", \"retain\", or \"copy\" specified");
    }

813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
    List<ObjCPropertyDeclaration *> **lastSymbols = &ast->symbols;
    for (List<Declaration*> *iter = simpleDecl->symbols; iter; iter = iter->next) {
        ObjCPropertyDeclaration *propDecl = control()->newObjCPropertyDeclaration(ast->firstToken(),
                                                                                  iter->value->name());
        propDecl->setType(iter->value->type());
        propDecl->setAttributes(propAttrs);
        propDecl->setGetterName(getterName);
        propDecl->setSetterName(setterName);
        _scope->enterSymbol(propDecl);

        *lastSymbols = new (translationUnit()->memoryPool()) List<ObjCPropertyDeclaration *>();
        (*lastSymbols)->value = propDecl;
        lastSymbols = &(*lastSymbols)->next;
    }

828
829
    return false;
}
830
831
832

bool CheckDeclaration::visit(QtEnumDeclarationAST *ast)
{
833
    checkQEnumsQFlagsNames(ast->enumerator_list, "Q_ENUMS");
834
835
836
837
838
    return false;
}

bool CheckDeclaration::visit(QtFlagsDeclarationAST *ast)
{
839
    checkQEnumsQFlagsNames(ast->flag_enums_list, "Q_FLAGS");
840
841
    return false;
}
842
843
844
845
846
847
848
849
850
851
852
853
854
855

bool CheckDeclaration::visit(QtPropertyDeclarationAST *ast)
{
    if (ast->type_id)
        semantic()->check(ast->type_id, _scope);
    if (ast->property_name)
        semantic()->check(ast->property_name, _scope);
    for (QtPropertyDeclarationItemListAST *iter = ast->property_declaration_items;
         iter; iter = iter->next) {
        if (iter->value)
            semantic()->check(iter->value->expression, _scope);
    }
    return false;
}
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890

void CheckDeclaration::checkQEnumsQFlagsNames(NameListAST *nameListAst,
                                              const char *declName)
{
    for (NameListAST *iter = nameListAst; iter; iter = iter->next) {
        if (!iter)
            continue;

        const Name *name = semantic()->check(iter->value, _scope);
        if (!name)
            continue;

        if (name->isNameId())
            continue;

        const QualifiedNameId *qName = name->asQualifiedNameId();
        if (!qName)
            translationUnit()->error(iter->firstToken(), "invalid name in %s",
                                     declName);
        else if (qName->isGlobal())
                translationUnit()->error(iter->firstToken(),
                                         "invalid name '%s' in %s",
                                         qName->identifier()->chars(), declName);
        else {
            for (unsigned i = 0; i < qName->nameCount(); ++i) {
                const Name *namePart = qName->nameAt(i);
                if (!namePart || !namePart->isNameId()) {
                    translationUnit()->error(iter->firstToken(),
                                             "invalid name '%s' in %s",
                                             qName->identifier()->chars(), declName);
                }
            }
        }
    }
}