CheckDeclaration.cpp 31.6 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

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

CheckDeclaration::~CheckDeclaration()
{ }

Roberto Raggi's avatar
Roberto Raggi committed
75
void CheckDeclaration::check(DeclarationAST *declaration, Scope *scope)
con's avatar
con committed
76
77
78
79
80
81
82
83
{
    Scope *previousScope = switchScope(scope);
    DeclarationAST *previousDeclaration = switchDeclaration(declaration);
    accept(declaration);
    (void) switchDeclaration(previousDeclaration);
    (void) switchScope(previousScope);
}

84
85
86
87
88
89
90
void CheckDeclaration::check(CtorInitializerAST *ast, Scope *scope)
{
    Scope *previousScope = switchScope(scope);
    accept(ast);
    (void) switchScope(previousScope);
}

con's avatar
con committed
91
92
93
94
95
96
97
98
99
100
101
102
103
104
DeclarationAST *CheckDeclaration::switchDeclaration(DeclarationAST *declaration)
{
    DeclarationAST *previousDeclaration = _declaration;
    _declaration = declaration;
    return previousDeclaration;
}

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

Roberto Raggi's avatar
Roberto Raggi committed
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
void CheckDeclaration::setDeclSpecifiers(Symbol *symbol, const FullySpecifiedType &declSpecifiers)
{
    if (! symbol)
        return;

    int storage = Symbol::NoStorage;

    if (declSpecifiers.isFriend())
        storage = Symbol::Friend;
    else if (declSpecifiers.isAuto())
        storage = Symbol::Auto;
    else if (declSpecifiers.isRegister())
        storage = Symbol::Register;
    else if (declSpecifiers.isStatic())
        storage = Symbol::Static;
    else if (declSpecifiers.isExtern())
        storage = Symbol::Extern;
    else if (declSpecifiers.isMutable())
        storage = Symbol::Mutable;
    else if (declSpecifiers.isTypedef())
        storage = Symbol::Typedef;

    symbol->setStorage(storage);

    if (Function *funTy = symbol->asFunction()) {
        if (declSpecifiers.isVirtual())
            funTy->setVirtual(true);
    }

    if (declSpecifiers.isDeprecated())
        symbol->setDeprecated(true);

    if (declSpecifiers.isUnavailable())
        symbol->setUnavailable(true);
}

con's avatar
con committed
141
142
143
144
145
void CheckDeclaration::checkFunctionArguments(Function *fun)
{
    if (! _checkAnonymousArguments)
        return;

Roberto Raggi's avatar
Roberto Raggi committed
146
    if (_scope->isClass() && fun->isPublic()) {
con's avatar
con committed
147
148
149
150
151
152
153
154
155
156
157
158
159
160
        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");
            }
        }
    }
}

bool CheckDeclaration::visit(SimpleDeclarationAST *ast)
{
Roberto Raggi's avatar
Roberto Raggi committed
161
162
    FullySpecifiedType declSpecifiers = semantic()->check(ast->decl_specifier_list, _scope);
    FullySpecifiedType qualTy = declSpecifiers.qualifiedType();
con's avatar
con committed
163

164
165
    if (ast->decl_specifier_list && ! ast->declarator_list) {
        ElaboratedTypeSpecifierAST *elab_type_spec = ast->decl_specifier_list->value->asElaboratedTypeSpecifier();
166

Roberto Raggi's avatar
Roberto Raggi committed
167
        if (! elab_type_spec && declSpecifiers.isFriend() && ast->decl_specifier_list->next && ! ast->decl_specifier_list->next->next) {
168
169
170
            // friend template class
            elab_type_spec = ast->decl_specifier_list->next->value->asElaboratedTypeSpecifier();
        }
171

172
173
        if (elab_type_spec) {
            unsigned sourceLocation = ast->decl_specifier_list->firstToken();
174

Roberto Raggi's avatar
Roberto Raggi committed
175
            const Name *name = semantic()->check(elab_type_spec->name, _scope);
176
            ForwardClassDeclaration *symbol =
177
                    control()->newForwardClassDeclaration(sourceLocation, name);
178

Roberto Raggi's avatar
Roberto Raggi committed
179
            setDeclSpecifiers(symbol, declSpecifiers);
180

Roberto Raggi's avatar
Roberto Raggi committed
181
            _scope->addMember(symbol);
182
183
184
185
            return false;
        }
    }

186
187
    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;
188
    const bool isQ_INVOKABLE = ast->qt_invokable_token && tokenKind(ast->qt_invokable_token) == T_Q_INVOKABLE;
189

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

196
        unsigned location = semantic()->location(it->value);
197
198
        if (! location)
            location = ast->firstToken();
199

200
201
        Function *fun = 0;
        if (declTy && 0 != (fun = declTy->asFunctionType())) {
202
            fun->setSourceLocation(location, translationUnit());
con's avatar
con committed
203
204
205
            fun->setScope(_scope);
            fun->setName(name);
            fun->setMethodKey(semantic()->currentMethodKey());
Roberto Raggi's avatar
Roberto Raggi committed
206
207
208

            setDeclSpecifiers(fun, declSpecifiers);

209
210
211
212
            if (isQ_SIGNAL)
                fun->setMethodKey(Function::SignalMethod);
            else if (isQ_SLOT)
                fun->setMethodKey(Function::SlotMethod);
213
            else if (isQ_INVOKABLE)
214
                fun->setMethodKey(Function::InvokableMethod);
con's avatar
con committed
215
216
217
218
219
220
221
            fun->setVisibility(semantic()->currentVisibility());
        } else if (semantic()->currentMethodKey() != Function::NormalMethod) {
            translationUnit()->warning(ast->firstToken(),
                                       "expected a function declaration");
        }

        Declaration *symbol = control()->newDeclaration(location, name);
222

con's avatar
con committed
223
        symbol->setType(declTy);
Roberto Raggi's avatar
Roberto Raggi committed
224
225

        setDeclSpecifiers(symbol, declSpecifiers);
con's avatar
con committed
226
227
228

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

Roberto Raggi's avatar
Roberto Raggi committed
229
230
        if (it->value && it->value->initializer) {
            FullySpecifiedType initTy = semantic()->check(it->value->initializer, _scope);
231
232
        }

Roberto Raggi's avatar
Roberto Raggi committed
233
234
235
236
        *decl_it = new (translationUnit()->memoryPool()) List<Declaration *>();
        (*decl_it)->value = symbol;
        decl_it = &(*decl_it)->next;

Roberto Raggi's avatar
Roberto Raggi committed
237
        _scope->addMember(symbol);
con's avatar
con committed
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
    }
    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);
254
    else if (accessSpecifier == T_Q_SIGNALS)
con's avatar
con committed
255
256
257
258
259
260
261
262
263
264
265
        semantic()->switchMethodKey(Function::SignalMethod);
    else
        semantic()->switchMethodKey(Function::NormalMethod);
    return false;
}

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

266
bool CheckDeclaration::visit(ExceptionDeclarationAST *ast)
con's avatar
con committed
267
{
Roberto Raggi's avatar
Roberto Raggi committed
268
    FullySpecifiedType ty = semantic()->check(ast->type_specifier_list, _scope);
269
270
    FullySpecifiedType qualTy = ty.qualifiedType();

Roberto Raggi's avatar
Roberto Raggi committed
271
    const Name *name = 0;
272
273
274
    FullySpecifiedType declTy = semantic()->check(ast->declarator, qualTy,
                                                  _scope, &name);

275
    unsigned location = semantic()->location(ast->declarator);
276
277
278
279
280
281
282
283
284
    if (! location) {
        if (ast->declarator)
            location = ast->declarator->firstToken();
        else
            location = ast->firstToken();
    }

    Declaration *symbol = control()->newDeclaration(location, name);
    symbol->setType(declTy);
Roberto Raggi's avatar
Roberto Raggi committed
285
    _scope->addMember(symbol);
286

con's avatar
con committed
287
288
289
290
291
    return false;
}

bool CheckDeclaration::visit(FunctionDefinitionAST *ast)
{
Roberto Raggi's avatar
Roberto Raggi committed
292
    FullySpecifiedType ty = semantic()->check(ast->decl_specifier_list, _scope);
con's avatar
con committed
293
    FullySpecifiedType qualTy = ty.qualifiedType();
Roberto Raggi's avatar
Roberto Raggi committed
294
    const Name *name = 0;
con's avatar
con committed
295
296
    FullySpecifiedType funTy = semantic()->check(ast->declarator, qualTy,
                                                 _scope, &name);
Roberto Raggi's avatar
Roberto Raggi committed
297
    if (! funTy->isFunctionType()) {
con's avatar
con committed
298
299
300
301
302
        translationUnit()->error(ast->firstToken(),
                                 "expected a function prototype");
        return false;
    }

303
304
305
306
307
    unsigned funStartOffset = tokenAt(ast->firstToken()).offset;
    if (ast->declarator && ast->declarator->core_declarator) {
        funStartOffset = tokenAt(ast->declarator->core_declarator->lastToken() - 1).end();
    }

308
    Function *fun = funTy->asFunctionType();
Roberto Raggi's avatar
Roberto Raggi committed
309
310
    setDeclSpecifiers(fun, ty);

Roberto Raggi's avatar
Roberto Raggi committed
311
312
    fun->setStartOffset(funStartOffset);
    fun->setEndOffset(tokenAt(ast->lastToken() - 1).end());
313
314
315
316
317
318
    if (ast->declarator) {
        unsigned loc = semantic()->location(ast->declarator);
        if (! loc)
            loc = ast->declarator->firstToken();
        fun->setSourceLocation(loc, translationUnit());
    }
con's avatar
con committed
319
320
321
322
    fun->setName(name);
    fun->setVisibility(semantic()->currentVisibility());
    fun->setMethodKey(semantic()->currentMethodKey());

323
324
    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;
325
    const bool isQ_INVOKABLE = ast->qt_invokable_token && tokenKind(ast->qt_invokable_token) == T_Q_INVOKABLE;
326
327
328
329
330

    if (isQ_SIGNAL)
        fun->setMethodKey(Function::SignalMethod);
    else if (isQ_SLOT)
        fun->setMethodKey(Function::SlotMethod);
331
    else if (isQ_INVOKABLE)
332
        fun->setMethodKey(Function::InvokableMethod);
333

con's avatar
con committed
334
335
    checkFunctionArguments(fun);

Roberto Raggi's avatar
Roberto Raggi committed
336
    ast->symbol = fun;
Roberto Raggi's avatar
Roberto Raggi committed
337
    _scope->addMember(fun);
con's avatar
con committed
338

339
340
    if (! semantic()->skipFunctionBodies())
        semantic()->checkFunctionDefinition(ast);
con's avatar
con committed
341
342
343
344

    return false;
}

Roberto Raggi's avatar
Roberto Raggi committed
345
346
347
bool CheckDeclaration::visit(MemInitializerAST *ast)
{
    (void) semantic()->check(ast->name, _scope);
348
349
350
    for (ExpressionListAST *it = ast->expression_list; it; it = it->next) {
        FullySpecifiedType ty = semantic()->check(it->value, _scope);
    }
Roberto Raggi's avatar
Roberto Raggi committed
351
352
353
    return false;
}

con's avatar
con committed
354
355
bool CheckDeclaration::visit(LinkageBodyAST *ast)
{
Roberto Raggi's avatar
Roberto Raggi committed
356
    for (DeclarationListAST *decl = ast->declaration_list; decl; decl = decl->next) {
357
       semantic()->check(decl->value, _scope);
con's avatar
con committed
358
359
360
361
362
363
    }
    return false;
}

bool CheckDeclaration::visit(LinkageSpecificationAST *ast)
{
Roberto Raggi's avatar
Roberto Raggi committed
364
    semantic()->check(ast->declaration, _scope);
con's avatar
con committed
365
366
367
368
369
    return false;
}

bool CheckDeclaration::visit(NamespaceAST *ast)
{
Roberto Raggi's avatar
Roberto Raggi committed
370
371
372
    const Name *namespaceName = 0;
    if (const Identifier *id = identifier(ast->identifier_token))
        namespaceName = control()->nameId(id);
373
374
375
376

    unsigned sourceLocation = ast->firstToken();
    if (ast->identifier_token)
        sourceLocation = ast->identifier_token;
377
378
379
    unsigned scopeStart = tokenAt(ast->firstToken()).offset;
    if (ast->linkage_body && ast->linkage_body->firstToken())
        scopeStart = tokenAt(ast->linkage_body->firstToken()).offset;
380
381

    Namespace *ns = control()->newNamespace(sourceLocation, namespaceName);
Roberto Raggi's avatar
Roberto Raggi committed
382
383
    ns->setStartOffset(scopeStart);
    ns->setEndOffset(tokenAt(ast->lastToken() - 1).end());
Roberto Raggi's avatar
Roberto Raggi committed
384
    ast->symbol = ns;
Roberto Raggi's avatar
Roberto Raggi committed
385
386
    _scope->addMember(ns);
    semantic()->check(ast->linkage_body, ns); // ### we'll do the merge later.
con's avatar
con committed
387
388
389
390

    return false;
}

391
bool CheckDeclaration::visit(NamespaceAliasDefinitionAST *ast)
con's avatar
con committed
392
{
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
    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);
    //ast->symbol = namespaceAlias;
Roberto Raggi's avatar
Roberto Raggi committed
408
    _scope->addMember(namespaceAlias);
409

con's avatar
con committed
410
411
412
413
414
    return false;
}

bool CheckDeclaration::visit(ParameterDeclarationAST *ast)
{
415
    unsigned sourceLocation = semantic()->location(ast->declarator);
416
417
418
419
420
421
    if (! sourceLocation) {
        if (ast->declarator)
            sourceLocation = ast->declarator->firstToken();
        else
            sourceLocation = ast->firstToken();
    }
422

Roberto Raggi's avatar
Roberto Raggi committed
423
    const Name *argName = 0;
Roberto Raggi's avatar
Roberto Raggi committed
424
    FullySpecifiedType ty = semantic()->check(ast->type_specifier_list, _scope);
con's avatar
con committed
425
426
427
    FullySpecifiedType argTy = semantic()->check(ast->declarator, ty.qualifiedType(),
                                                 _scope, &argName);
    FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope);
428
    Argument *arg = control()->newArgument(sourceLocation, argName);
Roberto Raggi's avatar
Roberto Raggi committed
429
    ast->symbol = arg;
430
431
432
433
434
435
436
437
438
439
440
441
442
    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
443
    arg->setType(argTy);
Roberto Raggi's avatar
Roberto Raggi committed
444
    _scope->addMember(arg);
con's avatar
con committed
445
446
447
448
449
    return false;
}

bool CheckDeclaration::visit(TemplateDeclarationAST *ast)
{
450
451
    Template *templ = control()->newTemplate(ast->firstToken());
    ast->symbol = templ;
452

Roberto Raggi's avatar
Roberto Raggi committed
453
    for (DeclarationListAST *param = ast->template_parameter_list; param; param = param->next) {
454
       semantic()->check(param->value, templ);
con's avatar
con committed
455
456
    }

457
458
459
460
461
462
463
464
465
466
    semantic()->check(ast->declaration, templ);

    if (Symbol *decl = templ->declaration()) {
        // propagate the name
        if (decl->sourceLocation())
            templ->setSourceLocation(decl->sourceLocation(), translationUnit());
        templ->setName(decl->name());
    }

    _scope->addMember(templ);
467

con's avatar
con committed
468
469
470
471
472
    return false;
}

bool CheckDeclaration::visit(TypenameTypeParameterAST *ast)
{
473
474
475
476
    unsigned sourceLocation = ast->firstToken();
    if (ast->name)
        sourceLocation = ast->name->firstToken();

Roberto Raggi's avatar
Roberto Raggi committed
477
    const Name *name = semantic()->check(ast->name, _scope);
478
479
480
    TypenameArgument *arg = control()->newTypenameArgument(sourceLocation, name);
    FullySpecifiedType ty = semantic()->check(ast->type_id, _scope);
    arg->setType(ty);
Roberto Raggi's avatar
Roberto Raggi committed
481
    ast->symbol = arg;
Roberto Raggi's avatar
Roberto Raggi committed
482
    _scope->addMember(arg);
con's avatar
con committed
483
484
485
486
487
    return false;
}

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

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

bool CheckDeclaration::visit(UsingAST *ast)
{
Roberto Raggi's avatar
Roberto Raggi committed
503
    const Name *name = semantic()->check(ast->name, _scope);
504
505
506
507
508
509

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

    UsingDeclaration *u = control()->newUsingDeclaration(sourceLocation, name);
Roberto Raggi's avatar
Roberto Raggi committed
510
    ast->symbol = u;
Roberto Raggi's avatar
Roberto Raggi committed
511
    _scope->addMember(u);
con's avatar
con committed
512
513
514
515
516
    return false;
}

bool CheckDeclaration::visit(UsingDirectiveAST *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();

    UsingNamespaceDirective *u = control()->newUsingNamespaceDirective(sourceLocation, name);
Roberto Raggi's avatar
Roberto Raggi committed
524
    ast->symbol = u;
Roberto Raggi's avatar
Roberto Raggi committed
525
    _scope->addMember(u);
526

Roberto Raggi's avatar
Roberto Raggi committed
527
    if (! (_scope->isBlock() || _scope->isNamespace()))
528
529
530
        translationUnit()->error(ast->firstToken(),
                                 "using-directive not within namespace or block scope");

con's avatar
con committed
531
532
533
    return false;
}

Erik Verbruggen's avatar
Erik Verbruggen committed
534
bool CheckDeclaration::visit(ObjCProtocolForwardDeclarationAST *ast)
535
536
537
538
{
    const unsigned sourceLocation = ast->firstToken();

    List<ObjCForwardProtocolDeclaration *> **symbolIter = &ast->symbols;
539
    for (NameListAST *it = ast->identifier_list; it; it = it->next) {
540
        unsigned declarationLocation;
Roberto Raggi's avatar
Roberto Raggi committed
541
542
        if (it->value)
            declarationLocation = it->value->firstToken();
543
544
545
        else
            declarationLocation = sourceLocation;

Roberto Raggi's avatar
Roberto Raggi committed
546
        const Name *protocolName = semantic()->check(it->value, _scope);
547
548
        ObjCForwardProtocolDeclaration *fwdProtocol = control()->newObjCForwardProtocolDeclaration(sourceLocation, protocolName);

Roberto Raggi's avatar
Roberto Raggi committed
549
        _scope->addMember(fwdProtocol);
550
551
552
553
554
555
556
557
558

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

    return false;
}

559
560
561
562
563
564
565
566
567
568
569
570
unsigned CheckDeclaration::calculateScopeStart(ObjCProtocolDeclarationAST *ast) const
{
    if (ast->protocol_refs)
        if (unsigned pos = ast->protocol_refs->lastToken())
            return tokenAt(pos - 1).end();
    if (ast->name)
        if (unsigned pos = ast->name->lastToken())
            return tokenAt(pos - 1).end();

    return tokenAt(ast->firstToken()).offset;
}

Erik Verbruggen's avatar
Erik Verbruggen committed
571
bool CheckDeclaration::visit(ObjCProtocolDeclarationAST *ast)
572
573
574
575
576
577
578
{
    unsigned sourceLocation;
    if (ast->name)
        sourceLocation = ast->name->firstToken();
    else
        sourceLocation = ast->firstToken();

Roberto Raggi's avatar
Roberto Raggi committed
579
    const Name *protocolName = semantic()->check(ast->name, _scope);
580
    ObjCProtocol *protocol = control()->newObjCProtocol(sourceLocation, protocolName);
Roberto Raggi's avatar
Roberto Raggi committed
581
582
    protocol->setStartOffset(calculateScopeStart(ast));
    protocol->setEndOffset(tokenAt(ast->lastToken() - 1).end());
583

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

    int previousObjCVisibility = semantic()->switchObjCVisibility(Function::Public);
Roberto Raggi's avatar
Roberto Raggi committed
594
    for (DeclarationListAST *it = ast->member_declaration_list; it; it = it->next) {
Roberto Raggi's avatar
Roberto Raggi committed
595
        semantic()->check(it->value, protocol);
596
597
598
599
    }
    (void) semantic()->switchObjCVisibility(previousObjCVisibility);

    ast->symbol = protocol;
Roberto Raggi's avatar
Roberto Raggi committed
600
    _scope->addMember(protocol);
601
602
603
604

    return false;
}

Erik Verbruggen's avatar
Erik Verbruggen committed
605
bool CheckDeclaration::visit(ObjCClassForwardDeclarationAST *ast)
606
607
608
609
{
    const unsigned sourceLocation = ast->firstToken();

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

Roberto Raggi's avatar
Roberto Raggi committed
617
        const Name *className = semantic()->check(it->value, _scope);
618
619
        ObjCForwardClassDeclaration *fwdClass = control()->newObjCForwardClassDeclaration(sourceLocation, className);

Roberto Raggi's avatar
Roberto Raggi committed
620
        _scope->addMember(fwdClass);
621
622
623
624
625
626
627
628
629

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

    return false;
}

630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
unsigned CheckDeclaration::calculateScopeStart(ObjCClassDeclarationAST *ast) const
{
    if (ast->inst_vars_decl)
        if (unsigned pos = ast->inst_vars_decl->lbrace_token)
            return tokenAt(pos).end();

    if (ast->protocol_refs)
        if (unsigned pos = ast->protocol_refs->lastToken())
            return tokenAt(pos - 1).end();

    if (ast->superclass)
        if (unsigned pos = ast->superclass->lastToken())
            return tokenAt(pos - 1).end();

    if (ast->colon_token)
        return tokenAt(ast->colon_token).end();

    if (ast->rparen_token)
        return tokenAt(ast->rparen_token).end();

    if (ast->category_name)
        if (unsigned pos = ast->category_name->lastToken())
            return tokenAt(pos - 1).end();

    if (ast->lparen_token)
        return tokenAt(ast->lparen_token).end();

    if (ast->class_name)
        if (unsigned pos = ast->class_name->lastToken())
            return tokenAt(pos - 1).end();

    return tokenAt(ast->firstToken()).offset;
}

Erik Verbruggen's avatar
Erik Verbruggen committed
664
bool CheckDeclaration::visit(ObjCClassDeclarationAST *ast)
665
666
667
668
669
670
671
{
    unsigned sourceLocation;
    if (ast->class_name)
        sourceLocation = ast->class_name->firstToken();
    else
        sourceLocation = ast->firstToken();

Roberto Raggi's avatar
Roberto Raggi committed
672
    const Name *className = semantic()->check(ast->class_name, _scope);
673
    ObjCClass *klass = control()->newObjCClass(sourceLocation, className);
Roberto Raggi's avatar
Roberto Raggi committed
674
675
    klass->setStartOffset(calculateScopeStart(ast));
    klass->setEndOffset(tokenAt(ast->lastToken() - 1).offset);
676
677
    ast->symbol = klass;

678
679
680
    klass->setInterface(ast->interface_token != 0);

    if (ast->category_name) {
Roberto Raggi's avatar
Roberto Raggi committed
681
        const Name *categoryName = semantic()->check(ast->category_name, _scope);
682
683
684
        klass->setCategoryName(categoryName);
    }

685
    if (ast->superclass) {
Roberto Raggi's avatar
Roberto Raggi committed
686
        const Name *superClassName = semantic()->check(ast->superclass, _scope);
687
688
689
690
691
        ObjCBaseClass *superKlass = control()->newObjCBaseClass(ast->superclass->firstToken(), superClassName);
        klass->setBaseClass(superKlass);
    }

    if (ast->protocol_refs && ast->protocol_refs->identifier_list) {
692
        for (NameListAST *iter = ast->protocol_refs->identifier_list; iter; iter = iter->next) {
Roberto Raggi's avatar
Roberto Raggi committed
693
            NameAST* name = iter->value;
Roberto Raggi's avatar
Roberto Raggi committed
694
            const Name *protocolName = semantic()->check(name, _scope);
695
696
697
698
699
            ObjCBaseProtocol *baseProtocol = control()->newObjCBaseProtocol(name->firstToken(), protocolName);
            klass->addProtocol(baseProtocol);
        }
    }

Roberto Raggi's avatar
Roberto Raggi committed
700
    _scope->addMember(klass);
701
702
703
704

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

    if (ast->inst_vars_decl) {
Roberto Raggi's avatar
Roberto Raggi committed
705
        for (DeclarationListAST *it = ast->inst_vars_decl->instance_variable_list; it; it = it->next) {
Roberto Raggi's avatar
Roberto Raggi committed
706
            semantic()->check(it->value, klass);
707
708
709
        }
    }

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

Roberto Raggi's avatar
Roberto Raggi committed
712
    for (DeclarationListAST *it = ast->member_declaration_list; it; it = it->next) {
Roberto Raggi's avatar
Roberto Raggi committed
713
        semantic()->check(it->value, klass);
714
715
716
717
718
719
720
721
722
    }

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

    return false;
}

bool CheckDeclaration::visit(ObjCMethodDeclarationAST *ast)
{
723
724
725
726
727
    ObjCMethodPrototypeAST *methodProto = ast->method_prototype;
    if (!methodProto)
        return false;
    ObjCSelectorAST *selector = methodProto->selector;
    if (!selector)
728
729
        return false;

730
    FullySpecifiedType ty = semantic()->check(methodProto, _scope);
731
732
    ObjCMethod *methodTy = ty.type()->asObjCMethodType();
    if (!methodTy)
733
734
        return false;

735
    Symbol *symbol;
Erik Verbruggen's avatar
Erik Verbruggen committed
736
    if (ast->function_body) {
737
        symbol = methodTy;
Roberto Raggi's avatar
Roberto Raggi committed
738
739
        methodTy->setStartOffset(tokenAt(ast->function_body->firstToken()).offset);
        methodTy->setEndOffset(tokenAt(ast->lastToken() - 1).end());
Erik Verbruggen's avatar
Erik Verbruggen committed
740
    } else {
741
        Declaration *decl = control()->newDeclaration(selector->firstToken(), methodTy->name());
742
        decl->setType(methodTy);
Erik Verbruggen's avatar
Erik Verbruggen committed
743
        symbol = decl;
744
        symbol->setStorage(methodTy->storage());
745
    }
746

747
    symbol->setVisibility(semantic()->currentObjCVisibility());
748
749
    if (ty.isDeprecated())
        symbol->setDeprecated(true);
750
751
    if (ty.isUnavailable())
        symbol->setUnavailable(true);
752

Roberto Raggi's avatar
Roberto Raggi committed
753
    _scope->addMember(symbol);
754

755
    if (ast->function_body && !semantic()->skipFunctionBodies()) {
Roberto Raggi's avatar
Roberto Raggi committed
756
        semantic()->check(ast->function_body, methodTy);
757
758
    }

759
760
761
    return false;
}

762
763
764
765
766
767
768
769
bool CheckDeclaration::visit(ObjCVisibilityDeclarationAST *ast)
{
    int accessSpecifier = tokenKind(ast->visibility_token);
    int visibility = semantic()->visibilityForObjCAccessSpecifier(accessSpecifier);
    semantic()->switchObjCVisibility(visibility);
    return false;
}

770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
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)
{
787
788
789
790
791
792
793
794
795
796
    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
797
    const Name *getterName = 0, *setterName = 0;
798

Roberto Raggi's avatar
Roberto Raggi committed
799
    for (ObjCPropertyAttributeListAST *iter= ast->property_attribute_list; iter; iter = iter->next) {
800
        ObjCPropertyAttributeAST *attrAst = iter->value;
801
802
803
        if (!attrAst)
            continue;

Roberto Raggi's avatar
Roberto Raggi committed
804
        const Identifier *attrId = identifier(attrAst->attribute_identifier_token);
805
        if (attrId == control()->objcGetterId()) {
806
807
            if (checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::Getter)) {
                getterName = semantic()->check(attrAst->method_selector, _scope);
808
            }
809
        } else if (attrId == control()->objcSetterId()) {
810
811
            if (checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::Setter)) {
                setterName = semantic()->check(attrAst->method_selector, _scope);
812
            }
813
        } else if (attrId == control()->objcReadwriteId()) {
814
            checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::ReadWrite);
815
        } else if (attrId == control()->objcReadonlyId()) {
816
            checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::ReadOnly);
817
        } else if (attrId == control()->objcAssignId()) {
818
            checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::Assign);
819
        } else if (attrId == control()->objcRetainId()) {
820
            checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::Retain);
821
        } else if (attrId == control()->objcCopyId()) {
822
            checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::Copy);
823
        } else if (attrId == control()->objcNonatomicId()) {
824
            checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::NonAtomic);
825
826
827
        }
    }

828
829
    if (propAttrs & ObjCPropertyDeclaration::ReadOnly &&
        propAttrs & ObjCPropertyDeclaration::ReadWrite)
830
831
832
        // 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");
833
    int setterSemAttrs = propAttrs & ObjCPropertyDeclaration::SetterSemanticsMask;
834
    if (setterSemAttrs
835
836
837
            && setterSemAttrs != ObjCPropertyDeclaration::Assign
            && setterSemAttrs != ObjCPropertyDeclaration::Retain
            && setterSemAttrs != ObjCPropertyDeclaration::Copy) {
838
839
840
841
842
        // 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");
    }

843
844
845
846
847
848
849
850
    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);
Roberto Raggi's avatar
Roberto Raggi committed
851
        _scope->addMember(propDecl);
852
853
854
855
856
857

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

858
859
    return false;
}
860
861
862

bool CheckDeclaration::visit(QtEnumDeclarationAST *ast)
{
863
    checkQEnumsQFlagsNames(ast->enumerator_list, "Q_ENUMS");
864
865
866
867
868
    return false;
}

bool CheckDeclaration::visit(QtFlagsDeclarationAST *ast)
{
869
    checkQEnumsQFlagsNames(ast->flag_enums_list, "Q_FLAGS");
870
871
    return false;
}
872
873
874
875
876
877
878
879
880
881
882
883
884
885

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;
}
886

887
static bool checkEnumName(const Name *name)
888
{
889
890
    if (! name)
        return false;
891

892
893
    else if (name->asNameId() != 0)
        return true;
894

895
896
897
    else if (const QualifiedNameId *q = name->asQualifiedNameId()) {
        if (! q->base())
            return false; // global qualified name
898

899
900
901
902
903
904
905
906
907
908
909
910
911
        if (checkEnumName(q->base()) && checkEnumName(q->name()))
            return true;
    }

    return false;
}

void CheckDeclaration::checkQEnumsQFlagsNames(NameListAST *nameListAst, const char *declName)
{
    for (NameListAST *iter = nameListAst; iter; iter = iter->next) {
        if (const Name *name = semantic()->check(iter->value, _scope)) {
            if (! checkEnumName(name))
                translationUnit()->error(iter->firstToken(), "invalid name in %s", declName);
912
913
914
        }
    }
}