Decl.cpp revision a1d5662d96465f0fddf8819d245da4d19b892eff
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/TypeLoc.h"
20#include "clang/AST/Stmt.h"
21#include "clang/AST/Expr.h"
22#include "clang/AST/PrettyPrinter.h"
23#include "clang/Basic/Builtins.h"
24#include "clang/Basic/IdentifierTable.h"
25#include <vector>
26
27using namespace clang;
28
29void Attr::Destroy(ASTContext &C) {
30  if (Next) {
31    Next->Destroy(C);
32    Next = 0;
33  }
34  this->~Attr();
35  C.Deallocate((void*)this);
36}
37
38/// \brief Return the TypeLoc wrapper for the type source info.
39TypeLoc DeclaratorInfo::getTypeLoc() const {
40  return TypeLoc::Create(Ty, (void*)(this + 1));
41}
42
43//===----------------------------------------------------------------------===//
44// Decl Allocation/Deallocation Method Implementations
45//===----------------------------------------------------------------------===//
46
47
48TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) {
49  return new (C) TranslationUnitDecl(C);
50}
51
52NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC,
53                                     SourceLocation L, IdentifierInfo *Id) {
54  return new (C) NamespaceDecl(DC, L, Id);
55}
56
57void NamespaceDecl::Destroy(ASTContext& C) {
58  // NamespaceDecl uses "NextDeclarator" to chain namespace declarations
59  // together. They are all top-level Decls.
60
61  this->~NamespaceDecl();
62  C.Deallocate((void *)this);
63}
64
65
66ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC,
67    SourceLocation L, IdentifierInfo *Id, QualType T) {
68  return new (C) ImplicitParamDecl(ImplicitParam, DC, L, Id, T);
69}
70
71const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) {
72  switch (SC) {
73  case VarDecl::None:          break;
74  case VarDecl::Auto:          return "auto"; break;
75  case VarDecl::Extern:        return "extern"; break;
76  case VarDecl::PrivateExtern: return "__private_extern__"; break;
77  case VarDecl::Register:      return "register"; break;
78  case VarDecl::Static:        return "static"; break;
79  }
80
81  assert(0 && "Invalid storage class");
82  return 0;
83}
84
85ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC,
86                                 SourceLocation L, IdentifierInfo *Id,
87                                 QualType T, DeclaratorInfo *DInfo,
88                                 StorageClass S, Expr *DefArg) {
89  return new (C) ParmVarDecl(ParmVar, DC, L, Id, T, DInfo, S, DefArg);
90}
91
92QualType ParmVarDecl::getOriginalType() const {
93  if (const OriginalParmVarDecl *PVD =
94      dyn_cast<OriginalParmVarDecl>(this))
95    return PVD->OriginalType;
96  return getType();
97}
98
99void VarDecl::setInit(ASTContext &C, Expr *I) {
100    if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>()) {
101      Eval->~EvaluatedStmt();
102      C.Deallocate(Eval);
103    }
104
105    Init = I;
106  }
107
108bool VarDecl::isExternC(ASTContext &Context) const {
109  if (!Context.getLangOptions().CPlusPlus)
110    return (getDeclContext()->isTranslationUnit() &&
111            getStorageClass() != Static) ||
112      (getDeclContext()->isFunctionOrMethod() && hasExternalStorage());
113
114  for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit();
115       DC = DC->getParent()) {
116    if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC))  {
117      if (Linkage->getLanguage() == LinkageSpecDecl::lang_c)
118        return getStorageClass() != Static;
119
120      break;
121    }
122
123    if (DC->isFunctionOrMethod())
124      return false;
125  }
126
127  return false;
128}
129
130OriginalParmVarDecl *OriginalParmVarDecl::Create(
131                                 ASTContext &C, DeclContext *DC,
132                                 SourceLocation L, IdentifierInfo *Id,
133                                 QualType T, DeclaratorInfo *DInfo,
134                                 QualType OT, StorageClass S, Expr *DefArg) {
135  return new (C) OriginalParmVarDecl(DC, L, Id, T, DInfo, OT, S, DefArg);
136}
137
138FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC,
139                                   SourceLocation L,
140                                   DeclarationName N, QualType T,
141                                   DeclaratorInfo *DInfo,
142                                   StorageClass S, bool isInline,
143                                   bool hasWrittenPrototype,
144                                   SourceLocation TypeSpecStartLoc) {
145  FunctionDecl *New
146    = new (C) FunctionDecl(Function, DC, L, N, T, DInfo, S, isInline,
147                           TypeSpecStartLoc);
148  New->HasWrittenPrototype = hasWrittenPrototype;
149  return New;
150}
151
152BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) {
153  return new (C) BlockDecl(DC, L);
154}
155
156FieldDecl *FieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
157                             IdentifierInfo *Id, QualType T,
158                             DeclaratorInfo *DInfo, Expr *BW,
159                             bool Mutable, SourceLocation TSSL) {
160  return new (C) FieldDecl(Decl::Field, DC, L, Id, T, DInfo, BW, Mutable, TSSL);
161}
162
163bool FieldDecl::isAnonymousStructOrUnion() const {
164  if (!isImplicit() || getDeclName())
165    return false;
166
167  if (const RecordType *Record = getType()->getAs<RecordType>())
168    return Record->getDecl()->isAnonymousStructOrUnion();
169
170  return false;
171}
172
173EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD,
174                                           SourceLocation L,
175                                           IdentifierInfo *Id, QualType T,
176                                           Expr *E, const llvm::APSInt &V) {
177  return new (C) EnumConstantDecl(CD, L, Id, T, E, V);
178}
179
180void EnumConstantDecl::Destroy(ASTContext& C) {
181  if (Init) Init->Destroy(C);
182  Decl::Destroy(C);
183}
184
185TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC,
186                                 SourceLocation L,
187                                 IdentifierInfo *Id, QualType T) {
188  return new (C) TypedefDecl(DC, L, Id, T);
189}
190
191EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
192                           IdentifierInfo *Id, SourceLocation TKL,
193                           EnumDecl *PrevDecl) {
194  EnumDecl *Enum = new (C) EnumDecl(DC, L, Id, PrevDecl, TKL);
195  C.getTypeDeclType(Enum, PrevDecl);
196  return Enum;
197}
198
199void EnumDecl::Destroy(ASTContext& C) {
200  Decl::Destroy(C);
201}
202
203void EnumDecl::completeDefinition(ASTContext &C, QualType NewType) {
204  assert(!isDefinition() && "Cannot redefine enums!");
205  IntegerType = NewType;
206  TagDecl::completeDefinition();
207}
208
209FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC,
210                                           SourceLocation L,
211                                           StringLiteral *Str) {
212  return new (C) FileScopeAsmDecl(DC, L, Str);
213}
214
215//===----------------------------------------------------------------------===//
216// NamedDecl Implementation
217//===----------------------------------------------------------------------===//
218
219std::string NamedDecl::getQualifiedNameAsString() const {
220  std::vector<std::string> Names;
221  std::string QualName;
222  const DeclContext *Ctx = getDeclContext();
223
224  if (Ctx->isFunctionOrMethod())
225    return getNameAsString();
226
227  while (Ctx) {
228    if (Ctx->isFunctionOrMethod())
229      // FIXME: That probably will happen, when D was member of local
230      // scope class/struct/union. How do we handle this case?
231      break;
232
233    if (const ClassTemplateSpecializationDecl *Spec
234          = dyn_cast<ClassTemplateSpecializationDecl>(Ctx)) {
235      const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
236      PrintingPolicy Policy(getASTContext().getLangOptions());
237      std::string TemplateArgsStr
238        = TemplateSpecializationType::PrintTemplateArgumentList(
239                                           TemplateArgs.getFlatArgumentList(),
240                                           TemplateArgs.flat_size(),
241                                           Policy);
242      Names.push_back(Spec->getIdentifier()->getName() + TemplateArgsStr);
243    } else if (const NamedDecl *ND = dyn_cast<NamedDecl>(Ctx))
244      Names.push_back(ND->getNameAsString());
245    else
246      break;
247
248    Ctx = Ctx->getParent();
249  }
250
251  std::vector<std::string>::reverse_iterator
252    I = Names.rbegin(),
253    End = Names.rend();
254
255  for (; I!=End; ++I)
256    QualName += *I + "::";
257
258  QualName += getNameAsString();
259
260  return QualName;
261}
262
263
264bool NamedDecl::declarationReplaces(NamedDecl *OldD) const {
265  assert(getDeclName() == OldD->getDeclName() && "Declaration name mismatch");
266
267  // UsingDirectiveDecl's are not really NamedDecl's, and all have same name.
268  // We want to keep it, unless it nominates same namespace.
269  if (getKind() == Decl::UsingDirective) {
270    return cast<UsingDirectiveDecl>(this)->getNominatedNamespace() ==
271           cast<UsingDirectiveDecl>(OldD)->getNominatedNamespace();
272  }
273
274  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this))
275    // For function declarations, we keep track of redeclarations.
276    return FD->getPreviousDeclaration() == OldD;
277
278  // For function templates, the underlying function declarations are linked.
279  if (const FunctionTemplateDecl *FunctionTemplate
280        = dyn_cast<FunctionTemplateDecl>(this))
281    if (const FunctionTemplateDecl *OldFunctionTemplate
282          = dyn_cast<FunctionTemplateDecl>(OldD))
283      return FunctionTemplate->getTemplatedDecl()
284               ->declarationReplaces(OldFunctionTemplate->getTemplatedDecl());
285
286  // For method declarations, we keep track of redeclarations.
287  if (isa<ObjCMethodDecl>(this))
288    return false;
289
290  // For non-function declarations, if the declarations are of the
291  // same kind then this must be a redeclaration, or semantic analysis
292  // would not have given us the new declaration.
293  return this->getKind() == OldD->getKind();
294}
295
296bool NamedDecl::hasLinkage() const {
297  if (const VarDecl *VD = dyn_cast<VarDecl>(this))
298    return VD->hasExternalStorage() || VD->isFileVarDecl();
299
300  if (isa<FunctionDecl>(this) && !isa<CXXMethodDecl>(this))
301    return true;
302
303  return false;
304}
305
306NamedDecl *NamedDecl::getUnderlyingDecl() {
307  NamedDecl *ND = this;
308  while (true) {
309    if (UsingDecl *UD = dyn_cast<UsingDecl>(ND))
310      ND = UD->getTargetDecl();
311    else if (ObjCCompatibleAliasDecl *AD
312              = dyn_cast<ObjCCompatibleAliasDecl>(ND))
313      return AD->getClassInterface();
314    else
315      return ND;
316  }
317}
318
319//===----------------------------------------------------------------------===//
320// VarDecl Implementation
321//===----------------------------------------------------------------------===//
322
323VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
324                         IdentifierInfo *Id, QualType T, DeclaratorInfo *DInfo,
325                         StorageClass S, SourceLocation TypeSpecStartLoc) {
326  return new (C) VarDecl(Var, DC, L, Id, T, DInfo, S, TypeSpecStartLoc);
327}
328
329void VarDecl::Destroy(ASTContext& C) {
330  Expr *Init = getInit();
331  if (Init) {
332    Init->Destroy(C);
333    if (EvaluatedStmt *Eval = this->Init.dyn_cast<EvaluatedStmt *>()) {
334      Eval->~EvaluatedStmt();
335      C.Deallocate(Eval);
336    }
337  }
338  this->~VarDecl();
339  C.Deallocate((void *)this);
340}
341
342VarDecl::~VarDecl() {
343}
344
345SourceRange VarDecl::getSourceRange() const {
346  if (getInit())
347    return SourceRange(getLocation(), getInit()->getLocEnd());
348  return SourceRange(getLocation(), getLocation());
349}
350
351VarDecl *VarDecl::getInstantiatedFromStaticDataMember() {
352  return getASTContext().getInstantiatedFromStaticDataMember(this);
353}
354
355bool VarDecl::isTentativeDefinition(ASTContext &Context) const {
356  if (!isFileVarDecl() || Context.getLangOptions().CPlusPlus)
357    return false;
358
359  const VarDecl *Def = 0;
360  return (!getDefinition(Def) &&
361          (getStorageClass() == None || getStorageClass() == Static));
362}
363
364const Expr *VarDecl::getDefinition(const VarDecl *&Def) const {
365  redecl_iterator I = redecls_begin(), E = redecls_end();
366  while (I != E && !I->getInit())
367    ++I;
368
369  if (I != E) {
370    Def = *I;
371    return I->getInit();
372  }
373  return 0;
374}
375
376VarDecl *VarDecl::getCanonicalDecl() {
377  return getFirstDeclaration();
378}
379
380//===----------------------------------------------------------------------===//
381// FunctionDecl Implementation
382//===----------------------------------------------------------------------===//
383
384void FunctionDecl::Destroy(ASTContext& C) {
385  if (Body && Body.isOffset())
386    Body.get(C.getExternalSource())->Destroy(C);
387
388  for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I)
389    (*I)->Destroy(C);
390
391  C.Deallocate(ParamInfo);
392
393  Decl::Destroy(C);
394}
395
396
397Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const {
398  for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) {
399    if (I->Body) {
400      Definition = *I;
401      return I->Body.get(getASTContext().getExternalSource());
402    }
403  }
404
405  return 0;
406}
407
408Stmt *FunctionDecl::getBodyIfAvailable() const {
409  for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) {
410    if (I->Body && !I->Body.isOffset()) {
411      return I->Body.get(0);
412    }
413  }
414
415  return 0;
416}
417
418void FunctionDecl::setBody(Stmt *B) {
419  Body = B;
420  if (B)
421    EndRangeLoc = B->getLocEnd();
422}
423
424bool FunctionDecl::isMain(ASTContext &Context) const {
425  return !Context.getLangOptions().Freestanding &&
426    getDeclContext()->getLookupContext()->isTranslationUnit() &&
427    getIdentifier() && getIdentifier()->isStr("main");
428}
429
430bool FunctionDecl::isExternC(ASTContext &Context) const {
431  // In C, any non-static, non-overloadable function has external
432  // linkage.
433  if (!Context.getLangOptions().CPlusPlus)
434    return getStorageClass() != Static && !getAttr<OverloadableAttr>();
435
436  for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit();
437       DC = DC->getParent()) {
438    if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC))  {
439      if (Linkage->getLanguage() == LinkageSpecDecl::lang_c)
440        return getStorageClass() != Static &&
441               !getAttr<OverloadableAttr>();
442
443      break;
444    }
445  }
446
447  return false;
448}
449
450bool FunctionDecl::isGlobal() const {
451  if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(this))
452    return Method->isStatic();
453
454  if (getStorageClass() == Static)
455    return false;
456
457  for (const DeclContext *DC = getDeclContext();
458       DC->isNamespace();
459       DC = DC->getParent()) {
460    if (const NamespaceDecl *Namespace = cast<NamespaceDecl>(DC)) {
461      if (!Namespace->getDeclName())
462        return false;
463      break;
464    }
465  }
466
467  return true;
468}
469
470/// \brief Returns a value indicating whether this function
471/// corresponds to a builtin function.
472///
473/// The function corresponds to a built-in function if it is
474/// declared at translation scope or within an extern "C" block and
475/// its name matches with the name of a builtin. The returned value
476/// will be 0 for functions that do not correspond to a builtin, a
477/// value of type \c Builtin::ID if in the target-independent range
478/// \c [1,Builtin::First), or a target-specific builtin value.
479unsigned FunctionDecl::getBuiltinID(ASTContext &Context) const {
480  if (!getIdentifier() || !getIdentifier()->getBuiltinID())
481    return 0;
482
483  unsigned BuiltinID = getIdentifier()->getBuiltinID();
484  if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
485    return BuiltinID;
486
487  // This function has the name of a known C library
488  // function. Determine whether it actually refers to the C library
489  // function or whether it just has the same name.
490
491  // If this is a static function, it's not a builtin.
492  if (getStorageClass() == Static)
493    return 0;
494
495  // If this function is at translation-unit scope and we're not in
496  // C++, it refers to the C library function.
497  if (!Context.getLangOptions().CPlusPlus &&
498      getDeclContext()->isTranslationUnit())
499    return BuiltinID;
500
501  // If the function is in an extern "C" linkage specification and is
502  // not marked "overloadable", it's the real function.
503  if (isa<LinkageSpecDecl>(getDeclContext()) &&
504      cast<LinkageSpecDecl>(getDeclContext())->getLanguage()
505        == LinkageSpecDecl::lang_c &&
506      !getAttr<OverloadableAttr>())
507    return BuiltinID;
508
509  // Not a builtin
510  return 0;
511}
512
513
514/// getNumParams - Return the number of parameters this function must have
515/// based on its FunctionType.  This is the length of the PararmInfo array
516/// after it has been created.
517unsigned FunctionDecl::getNumParams() const {
518  const FunctionType *FT = getType()->getAsFunctionType();
519  if (isa<FunctionNoProtoType>(FT))
520    return 0;
521  return cast<FunctionProtoType>(FT)->getNumArgs();
522
523}
524
525void FunctionDecl::setParams(ASTContext& C, ParmVarDecl **NewParamInfo,
526                             unsigned NumParams) {
527  assert(ParamInfo == 0 && "Already has param info!");
528  assert(NumParams == getNumParams() && "Parameter count mismatch!");
529
530  // Zero params -> null pointer.
531  if (NumParams) {
532    void *Mem = C.Allocate(sizeof(ParmVarDecl*)*NumParams);
533    ParamInfo = new (Mem) ParmVarDecl*[NumParams];
534    memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams);
535
536    // Update source range. The check below allows us to set EndRangeLoc before
537    // setting the parameters.
538    if (EndRangeLoc.isInvalid() || EndRangeLoc == getLocation())
539      EndRangeLoc = NewParamInfo[NumParams-1]->getLocEnd();
540  }
541}
542
543/// getMinRequiredArguments - Returns the minimum number of arguments
544/// needed to call this function. This may be fewer than the number of
545/// function parameters, if some of the parameters have default
546/// arguments (in C++).
547unsigned FunctionDecl::getMinRequiredArguments() const {
548  unsigned NumRequiredArgs = getNumParams();
549  while (NumRequiredArgs > 0
550         && getParamDecl(NumRequiredArgs-1)->hasDefaultArg())
551    --NumRequiredArgs;
552
553  return NumRequiredArgs;
554}
555
556bool FunctionDecl::hasActiveGNUInlineAttribute(ASTContext &Context) const {
557  if (!isInline() || !hasAttr<GNUInlineAttr>())
558    return false;
559
560  for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I)
561    if (I->isInline() && !I->hasAttr<GNUInlineAttr>())
562      return false;
563
564  return true;
565}
566
567bool FunctionDecl::isExternGNUInline(ASTContext &Context) const {
568  if (!hasActiveGNUInlineAttribute(Context))
569    return false;
570
571  for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I)
572    if (I->getStorageClass() == Extern && I->hasAttr<GNUInlineAttr>())
573      return true;
574
575  return false;
576}
577
578void
579FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
580  redeclarable_base::setPreviousDeclaration(PrevDecl);
581
582  if (FunctionTemplateDecl *FunTmpl = getDescribedFunctionTemplate()) {
583    FunctionTemplateDecl *PrevFunTmpl
584      = PrevDecl? PrevDecl->getDescribedFunctionTemplate() : 0;
585    assert((!PrevDecl || PrevFunTmpl) && "Function/function template mismatch");
586    FunTmpl->setPreviousDeclaration(PrevFunTmpl);
587  }
588}
589
590FunctionDecl *FunctionDecl::getCanonicalDecl() {
591  return getFirstDeclaration();
592}
593
594/// getOverloadedOperator - Which C++ overloaded operator this
595/// function represents, if any.
596OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const {
597  if (getDeclName().getNameKind() == DeclarationName::CXXOperatorName)
598    return getDeclName().getCXXOverloadedOperator();
599  else
600    return OO_None;
601}
602
603FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const {
604  if (FunctionTemplateSpecializationInfo *Info
605        = TemplateOrSpecialization
606            .dyn_cast<FunctionTemplateSpecializationInfo*>()) {
607    return Info->Template.getPointer();
608  }
609  return 0;
610}
611
612const TemplateArgumentList *
613FunctionDecl::getTemplateSpecializationArgs() const {
614  if (FunctionTemplateSpecializationInfo *Info
615      = TemplateOrSpecialization
616      .dyn_cast<FunctionTemplateSpecializationInfo*>()) {
617    return Info->TemplateArguments;
618  }
619  return 0;
620}
621
622void
623FunctionDecl::setFunctionTemplateSpecialization(ASTContext &Context,
624                                                FunctionTemplateDecl *Template,
625                                     const TemplateArgumentList *TemplateArgs,
626                                                void *InsertPos) {
627  FunctionTemplateSpecializationInfo *Info
628    = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>();
629  if (!Info)
630    Info = new (Context) FunctionTemplateSpecializationInfo;
631
632  Info->Function = this;
633  Info->Template.setPointer(Template);
634  Info->Template.setInt(0); // Implicit instantiation, unless told otherwise
635  Info->TemplateArguments = TemplateArgs;
636  TemplateOrSpecialization = Info;
637
638  // Insert this function template specialization into the set of known
639  // function template specialiations.
640  Template->getSpecializations().InsertNode(Info, InsertPos);
641}
642
643bool FunctionDecl::isExplicitSpecialization() const {
644  // FIXME: check this property for explicit specializations of member
645  // functions of class templates.
646  FunctionTemplateSpecializationInfo *Info
647    = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>();
648  if (!Info)
649    return false;
650
651  return Info->isExplicitSpecialization();
652}
653
654void FunctionDecl::setExplicitSpecialization(bool ES) {
655  // FIXME: set this property for explicit specializations of member functions
656  // of class templates.
657  FunctionTemplateSpecializationInfo *Info
658    = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>();
659  if (Info)
660    Info->setExplicitSpecialization(ES);
661}
662
663//===----------------------------------------------------------------------===//
664// TagDecl Implementation
665//===----------------------------------------------------------------------===//
666
667SourceRange TagDecl::getSourceRange() const {
668  SourceLocation E = RBraceLoc.isValid() ? RBraceLoc : getLocation();
669  return SourceRange(TagKeywordLoc, E);
670}
671
672TagDecl* TagDecl::getCanonicalDecl() {
673  return getFirstDeclaration();
674}
675
676void TagDecl::startDefinition() {
677  if (TagType *TagT = const_cast<TagType *>(TypeForDecl->getAs<TagType>())) {
678    TagT->decl.setPointer(this);
679    TagT->decl.setInt(1);
680  }
681}
682
683void TagDecl::completeDefinition() {
684  IsDefinition = true;
685  if (TagType *TagT = const_cast<TagType *>(TypeForDecl->getAs<TagType>())) {
686    assert(TagT->decl.getPointer() == this &&
687           "Attempt to redefine a tag definition?");
688    TagT->decl.setInt(0);
689  }
690}
691
692TagDecl* TagDecl::getDefinition(ASTContext& C) const {
693  if (isDefinition())
694    return const_cast<TagDecl *>(this);
695
696  for (redecl_iterator R = redecls_begin(), REnd = redecls_end();
697       R != REnd; ++R)
698    if (R->isDefinition())
699      return *R;
700
701  return 0;
702}
703
704//===----------------------------------------------------------------------===//
705// RecordDecl Implementation
706//===----------------------------------------------------------------------===//
707
708RecordDecl::RecordDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L,
709                       IdentifierInfo *Id, RecordDecl *PrevDecl,
710                       SourceLocation TKL)
711  : TagDecl(DK, TK, DC, L, Id, PrevDecl, TKL) {
712  HasFlexibleArrayMember = false;
713  AnonymousStructOrUnion = false;
714  HasObjectMember = false;
715  assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!");
716}
717
718RecordDecl *RecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
719                               SourceLocation L, IdentifierInfo *Id,
720                               SourceLocation TKL, RecordDecl* PrevDecl) {
721
722  RecordDecl* R = new (C) RecordDecl(Record, TK, DC, L, Id, PrevDecl, TKL);
723  C.getTypeDeclType(R, PrevDecl);
724  return R;
725}
726
727RecordDecl::~RecordDecl() {
728}
729
730void RecordDecl::Destroy(ASTContext& C) {
731  TagDecl::Destroy(C);
732}
733
734bool RecordDecl::isInjectedClassName() const {
735  return isImplicit() && getDeclName() && getDeclContext()->isRecord() &&
736    cast<RecordDecl>(getDeclContext())->getDeclName() == getDeclName();
737}
738
739/// completeDefinition - Notes that the definition of this type is now
740/// complete.
741void RecordDecl::completeDefinition(ASTContext& C) {
742  assert(!isDefinition() && "Cannot redefine record!");
743  TagDecl::completeDefinition();
744}
745
746//===----------------------------------------------------------------------===//
747// BlockDecl Implementation
748//===----------------------------------------------------------------------===//
749
750BlockDecl::~BlockDecl() {
751}
752
753void BlockDecl::Destroy(ASTContext& C) {
754  if (Body)
755    Body->Destroy(C);
756
757  for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I)
758    (*I)->Destroy(C);
759
760  C.Deallocate(ParamInfo);
761  Decl::Destroy(C);
762}
763
764void BlockDecl::setParams(ASTContext& C, ParmVarDecl **NewParamInfo,
765                          unsigned NParms) {
766  assert(ParamInfo == 0 && "Already has param info!");
767
768  // Zero params -> null pointer.
769  if (NParms) {
770    NumParams = NParms;
771    void *Mem = C.Allocate(sizeof(ParmVarDecl*)*NumParams);
772    ParamInfo = new (Mem) ParmVarDecl*[NumParams];
773    memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams);
774  }
775}
776
777unsigned BlockDecl::getNumParams() const {
778  return NumParams;
779}
780