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