Decl.cpp revision 42af25f865a82022a04bedeb483ac251c4412e29
1//===--- Decl.cpp - Declaration AST Node Implementation -------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the Decl subclasses.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/AST/Decl.h"
15#include "clang/AST/DeclCXX.h"
16#include "clang/AST/DeclObjC.h"
17#include "clang/AST/DeclTemplate.h"
18#include "clang/AST/ASTContext.h"
19#include "clang/AST/Stmt.h"
20#include "clang/AST/Expr.h"
21#include "clang/Basic/IdentifierTable.h"
22#include <vector>
23
24using namespace clang;
25
26void Attr::Destroy(ASTContext &C) {
27  if (Next) {
28    Next->Destroy(C);
29    Next = 0;
30  }
31  this->~Attr();
32  C.Deallocate((void*)this);
33}
34
35
36//===----------------------------------------------------------------------===//
37// Decl Allocation/Deallocation Method Implementations
38//===----------------------------------------------------------------------===//
39
40
41TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) {
42  return new (C) TranslationUnitDecl();
43}
44
45NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC,
46                                     SourceLocation L, IdentifierInfo *Id) {
47  return new (C) NamespaceDecl(DC, L, Id);
48}
49
50void NamespaceDecl::Destroy(ASTContext& C) {
51  // NamespaceDecl uses "NextDeclarator" to chain namespace declarations
52  // together. They are all top-level Decls.
53
54  this->~NamespaceDecl();
55  C.Deallocate((void *)this);
56}
57
58
59ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC,
60    SourceLocation L, IdentifierInfo *Id, QualType T) {
61  return new (C) ImplicitParamDecl(ImplicitParam, DC, L, Id, T);
62}
63
64const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) {
65  switch (SC) {
66  case VarDecl::None:          break;
67  case VarDecl::Auto:          return "auto"; break;
68  case VarDecl::Extern:        return "extern"; break;
69  case VarDecl::PrivateExtern: return "__private_extern__"; break;
70  case VarDecl::Register:      return "register"; break;
71  case VarDecl::Static:        return "static"; break;
72  }
73
74  assert(0 && "Invalid storage class");
75  return 0;
76}
77
78ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC,
79                                 SourceLocation L, IdentifierInfo *Id,
80                                 QualType T, StorageClass S,
81                                 Expr *DefArg) {
82  return new (C) ParmVarDecl(ParmVar, DC, L, Id, T, S, DefArg);
83}
84
85QualType ParmVarDecl::getOriginalType() const {
86  if (const OriginalParmVarDecl *PVD =
87      dyn_cast<OriginalParmVarDecl>(this))
88    return PVD->OriginalType;
89  return getType();
90}
91
92bool VarDecl::isExternC(ASTContext &Context) const {
93  if (!Context.getLangOptions().CPlusPlus)
94    return (getDeclContext()->isTranslationUnit() &&
95            getStorageClass() != Static) ||
96      (getDeclContext()->isFunctionOrMethod() && hasExternalStorage());
97
98  for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit();
99       DC = DC->getParent()) {
100    if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC))  {
101      if (Linkage->getLanguage() == LinkageSpecDecl::lang_c)
102        return getStorageClass() != Static;
103
104      break;
105    }
106
107    if (DC->isFunctionOrMethod())
108      return false;
109  }
110
111  return false;
112}
113
114OriginalParmVarDecl *OriginalParmVarDecl::Create(
115                                 ASTContext &C, DeclContext *DC,
116                                 SourceLocation L, IdentifierInfo *Id,
117                                 QualType T, QualType OT, StorageClass S,
118                                 Expr *DefArg) {
119  return new (C) OriginalParmVarDecl(DC, L, Id, T, OT, S, DefArg);
120}
121
122FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC,
123                                   SourceLocation L,
124                                   DeclarationName N, QualType T,
125                                   StorageClass S, bool isInline,
126                                   bool hasPrototype,
127                                   SourceLocation TypeSpecStartLoc) {
128  FunctionDecl *New
129    = new (C) FunctionDecl(Function, DC, L, N, T, S, isInline,
130                           TypeSpecStartLoc);
131  New->HasPrototype = hasPrototype;
132  return New;
133}
134
135BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) {
136  return new (C) BlockDecl(DC, L);
137}
138
139FieldDecl *FieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
140                             IdentifierInfo *Id, QualType T, Expr *BW,
141                             bool Mutable) {
142  return new (C) FieldDecl(Decl::Field, DC, L, Id, T, BW, Mutable);
143}
144
145bool FieldDecl::isAnonymousStructOrUnion() const {
146  if (!isImplicit() || getDeclName())
147    return false;
148
149  if (const RecordType *Record = getType()->getAsRecordType())
150    return Record->getDecl()->isAnonymousStructOrUnion();
151
152  return false;
153}
154
155EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD,
156                                           SourceLocation L,
157                                           IdentifierInfo *Id, QualType T,
158                                           Expr *E, const llvm::APSInt &V) {
159  return new (C) EnumConstantDecl(CD, L, Id, T, E, V);
160}
161
162void EnumConstantDecl::Destroy(ASTContext& C) {
163  if (Init) Init->Destroy(C);
164  Decl::Destroy(C);
165}
166
167TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC,
168                                 SourceLocation L,
169                                 IdentifierInfo *Id, QualType T) {
170  return new (C) TypedefDecl(DC, L, Id, T);
171}
172
173EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
174                           IdentifierInfo *Id,
175                           EnumDecl *PrevDecl) {
176  EnumDecl *Enum = new (C) EnumDecl(DC, L, Id);
177  C.getTypeDeclType(Enum, PrevDecl);
178  return Enum;
179}
180
181void EnumDecl::Destroy(ASTContext& C) {
182  Decl::Destroy(C);
183}
184
185void EnumDecl::completeDefinition(ASTContext &C, QualType NewType) {
186  assert(!isDefinition() && "Cannot redefine enums!");
187  IntegerType = NewType;
188  TagDecl::completeDefinition();
189}
190
191FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC,
192                                           SourceLocation L,
193                                           StringLiteral *Str) {
194  return new (C) FileScopeAsmDecl(DC, L, Str);
195}
196
197//===----------------------------------------------------------------------===//
198// NamedDecl Implementation
199//===----------------------------------------------------------------------===//
200
201std::string NamedDecl::getQualifiedNameAsString() const {
202  std::vector<std::string> Names;
203  std::string QualName;
204  const DeclContext *Ctx = getDeclContext();
205
206  if (Ctx->isFunctionOrMethod())
207    return getNameAsString();
208
209  while (Ctx) {
210    if (Ctx->isFunctionOrMethod())
211      // FIXME: That probably will happen, when D was member of local
212      // scope class/struct/union. How do we handle this case?
213      break;
214
215    if (const NamedDecl *ND = dyn_cast<NamedDecl>(Ctx))
216      Names.push_back(ND->getNameAsString());
217    else
218      break;
219
220    Ctx = Ctx->getParent();
221  }
222
223  std::vector<std::string>::reverse_iterator
224    I = Names.rbegin(),
225    End = Names.rend();
226
227  for (; I!=End; ++I)
228    QualName += *I + "::";
229
230  QualName += getNameAsString();
231
232  return QualName;
233}
234
235
236bool NamedDecl::declarationReplaces(NamedDecl *OldD) const {
237  assert(getDeclName() == OldD->getDeclName() && "Declaration name mismatch");
238
239  // UsingDirectiveDecl's are not really NamedDecl's, and all have same name.
240  // We want to keep it, unless it nominates same namespace.
241  if (getKind() == Decl::UsingDirective) {
242    return cast<UsingDirectiveDecl>(this)->getNominatedNamespace() ==
243           cast<UsingDirectiveDecl>(OldD)->getNominatedNamespace();
244  }
245
246  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this))
247    // For function declarations, we keep track of redeclarations.
248    return FD->getPreviousDeclaration() == OldD;
249
250  // For method declarations, we keep track of redeclarations.
251  if (isa<ObjCMethodDecl>(this))
252    return false;
253
254  // For non-function declarations, if the declarations are of the
255  // same kind then this must be a redeclaration, or semantic analysis
256  // would not have given us the new declaration.
257  return this->getKind() == OldD->getKind();
258}
259
260bool NamedDecl::hasLinkage() const {
261  if (const VarDecl *VD = dyn_cast<VarDecl>(this))
262    return VD->hasExternalStorage() || VD->isFileVarDecl();
263
264  if (isa<FunctionDecl>(this) && !isa<CXXMethodDecl>(this))
265    return true;
266
267  return false;
268}
269
270//===----------------------------------------------------------------------===//
271// VarDecl Implementation
272//===----------------------------------------------------------------------===//
273
274VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
275                         IdentifierInfo *Id, QualType T, StorageClass S,
276                         SourceLocation TypeSpecStartLoc) {
277  return new (C) VarDecl(Var, DC, L, Id, T, S, TypeSpecStartLoc);
278}
279
280void VarDecl::Destroy(ASTContext& C) {
281  Expr *Init = getInit();
282  if (Init)
283    Init->Destroy(C);
284  this->~VarDecl();
285  C.Deallocate((void *)this);
286}
287
288VarDecl::~VarDecl() {
289}
290
291bool VarDecl::isTentativeDefinition(ASTContext &Context) const {
292  if (!isFileVarDecl() || Context.getLangOptions().CPlusPlus)
293    return false;
294
295  const VarDecl *Def = 0;
296  return (!getDefinition(Def) &&
297          (getStorageClass() == None || getStorageClass() == Static));
298}
299
300const Expr *VarDecl::getDefinition(const VarDecl *&Def) const {
301  Def = this;
302  while (Def && !Def->getInit())
303    Def = Def->getPreviousDeclaration();
304
305  return Def? Def->getInit() : 0;
306}
307
308//===----------------------------------------------------------------------===//
309// FunctionDecl Implementation
310//===----------------------------------------------------------------------===//
311
312void FunctionDecl::Destroy(ASTContext& C) {
313  if (Body && Body.isOffset())
314    Body.get(C.getExternalSource())->Destroy(C);
315
316  for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I)
317    (*I)->Destroy(C);
318
319  C.Deallocate(ParamInfo);
320
321  Decl::Destroy(C);
322}
323
324
325Stmt *FunctionDecl::getBody(ASTContext &Context,
326                            const FunctionDecl *&Definition) const {
327  for (const FunctionDecl *FD = this; FD != 0; FD = FD->PreviousDeclaration) {
328    if (FD->Body) {
329      Definition = FD;
330      return FD->Body.get(Context.getExternalSource());
331    }
332  }
333
334  return 0;
335}
336
337Stmt *FunctionDecl::getBodyIfAvailable() const {
338  for (const FunctionDecl *FD = this; FD != 0; FD = FD->PreviousDeclaration) {
339    if (FD->Body && !FD->Body.isOffset()) {
340      return FD->Body.get(0);
341    }
342  }
343
344  return 0;
345}
346
347bool FunctionDecl::isMain() const {
348  return getDeclContext()->getLookupContext()->isTranslationUnit() &&
349    getIdentifier() && getIdentifier()->isStr("main");
350}
351
352bool FunctionDecl::isExternC(ASTContext &Context) const {
353  // In C, any non-static, non-overloadable function has external
354  // linkage.
355  if (!Context.getLangOptions().CPlusPlus)
356    return getStorageClass() != Static && !getAttr<OverloadableAttr>();
357
358  for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit();
359       DC = DC->getParent()) {
360    if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC))  {
361      if (Linkage->getLanguage() == LinkageSpecDecl::lang_c)
362        return getStorageClass() != Static && !getAttr<OverloadableAttr>();
363
364      break;
365    }
366  }
367
368  return false;
369}
370
371bool FunctionDecl::isGlobal() const {
372  if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(this))
373    return Method->isStatic();
374
375  if (getStorageClass() == Static)
376    return false;
377
378  for (const DeclContext *DC = getDeclContext();
379       DC->isNamespace();
380       DC = DC->getParent()) {
381    if (const NamespaceDecl *Namespace = cast<NamespaceDecl>(DC)) {
382      if (!Namespace->getDeclName())
383        return false;
384      break;
385    }
386  }
387
388  return true;
389}
390
391/// \brief Returns a value indicating whether this function
392/// corresponds to a builtin function.
393///
394/// The function corresponds to a built-in function if it is
395/// declared at translation scope or within an extern "C" block and
396/// its name matches with the name of a builtin. The returned value
397/// will be 0 for functions that do not correspond to a builtin, a
398/// value of type \c Builtin::ID if in the target-independent range
399/// \c [1,Builtin::First), or a target-specific builtin value.
400unsigned FunctionDecl::getBuiltinID(ASTContext &Context) const {
401  if (!getIdentifier() || !getIdentifier()->getBuiltinID())
402    return 0;
403
404  unsigned BuiltinID = getIdentifier()->getBuiltinID();
405  if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
406    return BuiltinID;
407
408  // This function has the name of a known C library
409  // function. Determine whether it actually refers to the C library
410  // function or whether it just has the same name.
411
412  // If this is a static function, it's not a builtin.
413  if (getStorageClass() == Static)
414    return 0;
415
416  // If this function is at translation-unit scope and we're not in
417  // C++, it refers to the C library function.
418  if (!Context.getLangOptions().CPlusPlus &&
419      getDeclContext()->isTranslationUnit())
420    return BuiltinID;
421
422  // If the function is in an extern "C" linkage specification and is
423  // not marked "overloadable", it's the real function.
424  if (isa<LinkageSpecDecl>(getDeclContext()) &&
425      cast<LinkageSpecDecl>(getDeclContext())->getLanguage()
426        == LinkageSpecDecl::lang_c &&
427      !getAttr<OverloadableAttr>())
428    return BuiltinID;
429
430  // Not a builtin
431  return 0;
432}
433
434
435/// getNumParams - Return the number of parameters this function must have
436/// based on its FunctionType.  This is the length of the PararmInfo array
437/// after it has been created.
438unsigned FunctionDecl::getNumParams() const {
439  const FunctionType *FT = getType()->getAsFunctionType();
440  if (isa<FunctionNoProtoType>(FT))
441    return 0;
442  return cast<FunctionProtoType>(FT)->getNumArgs();
443
444}
445
446void FunctionDecl::setParams(ASTContext& C, ParmVarDecl **NewParamInfo,
447                             unsigned NumParams) {
448  assert(ParamInfo == 0 && "Already has param info!");
449  assert(NumParams == getNumParams() && "Parameter count mismatch!");
450
451  // Zero params -> null pointer.
452  if (NumParams) {
453    void *Mem = C.Allocate(sizeof(ParmVarDecl*)*NumParams);
454    ParamInfo = new (Mem) ParmVarDecl*[NumParams];
455    memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams);
456  }
457}
458
459/// getMinRequiredArguments - Returns the minimum number of arguments
460/// needed to call this function. This may be fewer than the number of
461/// function parameters, if some of the parameters have default
462/// arguments (in C++).
463unsigned FunctionDecl::getMinRequiredArguments() const {
464  unsigned NumRequiredArgs = getNumParams();
465  while (NumRequiredArgs > 0
466         && getParamDecl(NumRequiredArgs-1)->getDefaultArg())
467    --NumRequiredArgs;
468
469  return NumRequiredArgs;
470}
471
472bool FunctionDecl::hasActiveGNUInlineAttribute() const {
473  if (!isInline() || !hasAttr<GNUInlineAttr>())
474    return false;
475
476  for (const FunctionDecl *FD = getPreviousDeclaration(); FD;
477       FD = FD->getPreviousDeclaration()) {
478    if (FD->isInline() && !FD->hasAttr<GNUInlineAttr>())
479      return false;
480  }
481
482  return true;
483}
484
485bool FunctionDecl::isExternGNUInline() const {
486  if (!hasActiveGNUInlineAttribute())
487    return false;
488
489  for (const FunctionDecl *FD = this; FD; FD = FD->getPreviousDeclaration())
490    if (FD->getStorageClass() == Extern && FD->hasAttr<GNUInlineAttr>())
491      return true;
492
493  return false;
494}
495
496/// getOverloadedOperator - Which C++ overloaded operator this
497/// function represents, if any.
498OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const {
499  if (getDeclName().getNameKind() == DeclarationName::CXXOperatorName)
500    return getDeclName().getCXXOverloadedOperator();
501  else
502    return OO_None;
503}
504
505//===----------------------------------------------------------------------===//
506// TagDecl Implementation
507//===----------------------------------------------------------------------===//
508
509bool TagDecl::isDependentType() const {
510  if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(this))
511    if (Record->getDescribedClassTemplate())
512      return true;
513
514  if (const TagDecl *TD = dyn_cast_or_null<TagDecl>(getDeclContext()))
515    return TD->isDependentType();
516
517  // FIXME: Tag types declared function templates are dependent types.
518  // FIXME: Look through block scopes.
519  return false;
520}
521
522void TagDecl::startDefinition() {
523  TagType *TagT = const_cast<TagType *>(TypeForDecl->getAsTagType());
524  TagT->decl.setPointer(this);
525  TagT->getAsTagType()->decl.setInt(1);
526}
527
528void TagDecl::completeDefinition() {
529  assert((!TypeForDecl ||
530          TypeForDecl->getAsTagType()->decl.getPointer() == this) &&
531         "Attempt to redefine a tag definition?");
532  IsDefinition = true;
533  TagType *TagT = const_cast<TagType *>(TypeForDecl->getAsTagType());
534  TagT->decl.setPointer(this);
535  TagT->decl.setInt(0);
536}
537
538TagDecl* TagDecl::getDefinition(ASTContext& C) const {
539  QualType T = C.getTypeDeclType(const_cast<TagDecl*>(this));
540  TagDecl* D = cast<TagDecl>(T->getAsTagType()->getDecl());
541  return D->isDefinition() ? D : 0;
542}
543
544//===----------------------------------------------------------------------===//
545// RecordDecl Implementation
546//===----------------------------------------------------------------------===//
547
548RecordDecl::RecordDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L,
549                       IdentifierInfo *Id)
550  : TagDecl(DK, TK, DC, L, Id) {
551  HasFlexibleArrayMember = false;
552  AnonymousStructOrUnion = false;
553  assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!");
554}
555
556RecordDecl *RecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
557                               SourceLocation L, IdentifierInfo *Id,
558                               RecordDecl* PrevDecl) {
559
560  RecordDecl* R = new (C) RecordDecl(Record, TK, DC, L, Id);
561  C.getTypeDeclType(R, PrevDecl);
562  return R;
563}
564
565RecordDecl::~RecordDecl() {
566}
567
568void RecordDecl::Destroy(ASTContext& C) {
569  TagDecl::Destroy(C);
570}
571
572bool RecordDecl::isInjectedClassName() const {
573  return isImplicit() && getDeclName() && getDeclContext()->isRecord() &&
574    cast<RecordDecl>(getDeclContext())->getDeclName() == getDeclName();
575}
576
577/// completeDefinition - Notes that the definition of this type is now
578/// complete.
579void RecordDecl::completeDefinition(ASTContext& C) {
580  assert(!isDefinition() && "Cannot redefine record!");
581  TagDecl::completeDefinition();
582}
583
584//===----------------------------------------------------------------------===//
585// BlockDecl Implementation
586//===----------------------------------------------------------------------===//
587
588BlockDecl::~BlockDecl() {
589}
590
591void BlockDecl::Destroy(ASTContext& C) {
592  if (Body)
593    Body->Destroy(C);
594
595  for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I)
596    (*I)->Destroy(C);
597
598  C.Deallocate(ParamInfo);
599  Decl::Destroy(C);
600}
601
602void BlockDecl::setParams(ASTContext& C, ParmVarDecl **NewParamInfo,
603                          unsigned NParms) {
604  assert(ParamInfo == 0 && "Already has param info!");
605
606  // Zero params -> null pointer.
607  if (NParms) {
608    NumParams = NParms;
609    void *Mem = C.Allocate(sizeof(ParmVarDecl*)*NumParams);
610    ParamInfo = new (Mem) ParmVarDecl*[NumParams];
611    memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams);
612  }
613}
614
615unsigned BlockDecl::getNumParams() const {
616  return NumParams;
617}
618