xref: /llvm-project-15.0.7/clang/lib/AST/Decl.cpp (revision 89141b5a)
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 
26 using namespace clang;
27 
28 void 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 
43 TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) {
44   return new (C) TranslationUnitDecl(C);
45 }
46 
47 NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC,
48                                      SourceLocation L, IdentifierInfo *Id) {
49   return new (C) NamespaceDecl(DC, L, Id);
50 }
51 
52 void 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 
61 ImplicitParamDecl *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 
66 const 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 
80 ParmVarDecl *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 
87 QualType ParmVarDecl::getOriginalType() const {
88   if (const OriginalParmVarDecl *PVD =
89       dyn_cast<OriginalParmVarDecl>(this))
90     return PVD->OriginalType;
91   return getType();
92 }
93 
94 void 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 
103 bool 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 
125 OriginalParmVarDecl *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 
133 FunctionDecl *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 
146 BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) {
147   return new (C) BlockDecl(DC, L);
148 }
149 
150 FieldDecl *FieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
151                              IdentifierInfo *Id, QualType T, Expr *BW,
152                              bool Mutable) {
153   return new (C) FieldDecl(Decl::Field, DC, L, Id, T, BW, Mutable);
154 }
155 
156 bool 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 
166 EnumConstantDecl *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 
173 void EnumConstantDecl::Destroy(ASTContext& C) {
174   if (Init) Init->Destroy(C);
175   Decl::Destroy(C);
176 }
177 
178 TypedefDecl *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 
184 EnumDecl *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 
192 void EnumDecl::Destroy(ASTContext& C) {
193   Decl::Destroy(C);
194 }
195 
196 void EnumDecl::completeDefinition(ASTContext &C, QualType NewType) {
197   assert(!isDefinition() && "Cannot redefine enums!");
198   IntegerType = NewType;
199   TagDecl::completeDefinition();
200 }
201 
202 FileScopeAsmDecl *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 
212 std::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 
257 bool 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 
289 bool 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 
299 NamedDecl *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 
316 VarDecl *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 
322 void 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 
335 VarDecl::~VarDecl() {
336 }
337 
338 SourceRange VarDecl::getSourceRange() const {
339   if (getInit())
340     return SourceRange(getLocation(), getInit()->getLocEnd());
341   return SourceRange(getLocation(), getLocation());
342 }
343 
344 bool 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 
353 const Expr *VarDecl::getDefinition(const VarDecl *&Def) const {
354   Def = this;
355   while (Def && !Def->getInit())
356     Def = Def->getPreviousDeclaration();
357 
358   return Def? Def->getInit() : 0;
359 }
360 
361 //===----------------------------------------------------------------------===//
362 // FunctionDecl Implementation
363 //===----------------------------------------------------------------------===//
364 
365 void FunctionDecl::Destroy(ASTContext& C) {
366   if (Body && Body.isOffset())
367     Body.get(C.getExternalSource())->Destroy(C);
368 
369   for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I)
370     (*I)->Destroy(C);
371 
372   C.Deallocate(ParamInfo);
373 
374   Decl::Destroy(C);
375 }
376 
377 
378 Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const {
379   for (const FunctionDecl *FD = this; FD != 0; FD = FD->PreviousDeclaration) {
380     if (FD->Body) {
381       Definition = FD;
382       return FD->Body.get(getASTContext().getExternalSource());
383     }
384   }
385 
386   return 0;
387 }
388 
389 Stmt *FunctionDecl::getBodyIfAvailable() const {
390   for (const FunctionDecl *FD = this; FD != 0; FD = FD->PreviousDeclaration) {
391     if (FD->Body && !FD->Body.isOffset()) {
392       return FD->Body.get(0);
393     }
394   }
395 
396   return 0;
397 }
398 
399 void FunctionDecl::setBody(Stmt *B) {
400   Body = B;
401   if (B)
402     EndRangeLoc = B->getLocEnd();
403 }
404 
405 bool FunctionDecl::isMain() const {
406   return getDeclContext()->getLookupContext()->isTranslationUnit() &&
407     getIdentifier() && getIdentifier()->isStr("main");
408 }
409 
410 bool FunctionDecl::isExternC(ASTContext &Context) const {
411   // In C, any non-static, non-overloadable function has external
412   // linkage.
413   if (!Context.getLangOptions().CPlusPlus)
414     return getStorageClass() != Static && !getAttr<OverloadableAttr>();
415 
416   for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit();
417        DC = DC->getParent()) {
418     if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC))  {
419       if (Linkage->getLanguage() == LinkageSpecDecl::lang_c)
420         return getStorageClass() != Static &&
421                !getAttr<OverloadableAttr>();
422 
423       break;
424     }
425   }
426 
427   return false;
428 }
429 
430 bool FunctionDecl::isGlobal() const {
431   if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(this))
432     return Method->isStatic();
433 
434   if (getStorageClass() == Static)
435     return false;
436 
437   for (const DeclContext *DC = getDeclContext();
438        DC->isNamespace();
439        DC = DC->getParent()) {
440     if (const NamespaceDecl *Namespace = cast<NamespaceDecl>(DC)) {
441       if (!Namespace->getDeclName())
442         return false;
443       break;
444     }
445   }
446 
447   return true;
448 }
449 
450 /// \brief Returns a value indicating whether this function
451 /// corresponds to a builtin function.
452 ///
453 /// The function corresponds to a built-in function if it is
454 /// declared at translation scope or within an extern "C" block and
455 /// its name matches with the name of a builtin. The returned value
456 /// will be 0 for functions that do not correspond to a builtin, a
457 /// value of type \c Builtin::ID if in the target-independent range
458 /// \c [1,Builtin::First), or a target-specific builtin value.
459 unsigned FunctionDecl::getBuiltinID(ASTContext &Context) const {
460   if (!getIdentifier() || !getIdentifier()->getBuiltinID())
461     return 0;
462 
463   unsigned BuiltinID = getIdentifier()->getBuiltinID();
464   if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
465     return BuiltinID;
466 
467   // This function has the name of a known C library
468   // function. Determine whether it actually refers to the C library
469   // function or whether it just has the same name.
470 
471   // If this is a static function, it's not a builtin.
472   if (getStorageClass() == Static)
473     return 0;
474 
475   // If this function is at translation-unit scope and we're not in
476   // C++, it refers to the C library function.
477   if (!Context.getLangOptions().CPlusPlus &&
478       getDeclContext()->isTranslationUnit())
479     return BuiltinID;
480 
481   // If the function is in an extern "C" linkage specification and is
482   // not marked "overloadable", it's the real function.
483   if (isa<LinkageSpecDecl>(getDeclContext()) &&
484       cast<LinkageSpecDecl>(getDeclContext())->getLanguage()
485         == LinkageSpecDecl::lang_c &&
486       !getAttr<OverloadableAttr>())
487     return BuiltinID;
488 
489   // Not a builtin
490   return 0;
491 }
492 
493 
494 /// getNumParams - Return the number of parameters this function must have
495 /// based on its FunctionType.  This is the length of the PararmInfo array
496 /// after it has been created.
497 unsigned FunctionDecl::getNumParams() const {
498   const FunctionType *FT = getType()->getAsFunctionType();
499   if (isa<FunctionNoProtoType>(FT))
500     return 0;
501   return cast<FunctionProtoType>(FT)->getNumArgs();
502 
503 }
504 
505 void FunctionDecl::setParams(ASTContext& C, ParmVarDecl **NewParamInfo,
506                              unsigned NumParams) {
507   assert(ParamInfo == 0 && "Already has param info!");
508   assert(NumParams == getNumParams() && "Parameter count mismatch!");
509 
510   // Zero params -> null pointer.
511   if (NumParams) {
512     void *Mem = C.Allocate(sizeof(ParmVarDecl*)*NumParams);
513     ParamInfo = new (Mem) ParmVarDecl*[NumParams];
514     memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams);
515 
516     // Update source range. The check below allows us to set EndRangeLoc before
517     // setting the parameters.
518     if (EndRangeLoc.isInvalid() || EndRangeLoc == getLocation())
519       EndRangeLoc = NewParamInfo[NumParams-1]->getLocEnd();
520   }
521 }
522 
523 /// getMinRequiredArguments - Returns the minimum number of arguments
524 /// needed to call this function. This may be fewer than the number of
525 /// function parameters, if some of the parameters have default
526 /// arguments (in C++).
527 unsigned FunctionDecl::getMinRequiredArguments() const {
528   unsigned NumRequiredArgs = getNumParams();
529   while (NumRequiredArgs > 0
530          && getParamDecl(NumRequiredArgs-1)->hasDefaultArg())
531     --NumRequiredArgs;
532 
533   return NumRequiredArgs;
534 }
535 
536 bool FunctionDecl::hasActiveGNUInlineAttribute(ASTContext &Context) const {
537   if (!isInline() || !hasAttr<GNUInlineAttr>())
538     return false;
539 
540   for (const FunctionDecl *FD = getPreviousDeclaration(); FD;
541        FD = FD->getPreviousDeclaration()) {
542     if (FD->isInline() && !FD->hasAttr<GNUInlineAttr>())
543       return false;
544   }
545 
546   return true;
547 }
548 
549 bool FunctionDecl::isExternGNUInline(ASTContext &Context) const {
550   if (!hasActiveGNUInlineAttribute(Context))
551     return false;
552 
553   for (const FunctionDecl *FD = this; FD; FD = FD->getPreviousDeclaration())
554     if (FD->getStorageClass() == Extern && FD->hasAttr<GNUInlineAttr>())
555       return true;
556 
557   return false;
558 }
559 
560 void
561 FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
562   PreviousDeclaration = PrevDecl;
563 
564   if (FunctionTemplateDecl *FunTmpl = getDescribedFunctionTemplate()) {
565     FunctionTemplateDecl *PrevFunTmpl
566       = PrevDecl? PrevDecl->getDescribedFunctionTemplate() : 0;
567     assert((!PrevDecl || PrevFunTmpl) && "Function/function template mismatch");
568     FunTmpl->setPreviousDeclaration(PrevFunTmpl);
569   }
570 }
571 
572 /// getOverloadedOperator - Which C++ overloaded operator this
573 /// function represents, if any.
574 OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const {
575   if (getDeclName().getNameKind() == DeclarationName::CXXOperatorName)
576     return getDeclName().getCXXOverloadedOperator();
577   else
578     return OO_None;
579 }
580 
581 FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const {
582   if (FunctionTemplateSpecializationInfo *Info
583         = TemplateOrSpecialization
584             .dyn_cast<FunctionTemplateSpecializationInfo*>()) {
585     return Info->Template.getPointer();
586   }
587   return 0;
588 }
589 
590 const TemplateArgumentList *
591 FunctionDecl::getTemplateSpecializationArgs() const {
592   if (FunctionTemplateSpecializationInfo *Info
593       = TemplateOrSpecialization
594       .dyn_cast<FunctionTemplateSpecializationInfo*>()) {
595     return Info->TemplateArguments;
596   }
597   return 0;
598 }
599 
600 void
601 FunctionDecl::setFunctionTemplateSpecialization(ASTContext &Context,
602                                                 FunctionTemplateDecl *Template,
603                                      const TemplateArgumentList *TemplateArgs,
604                                                 void *InsertPos) {
605   FunctionTemplateSpecializationInfo *Info
606     = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>();
607   if (!Info)
608     Info = new (Context) FunctionTemplateSpecializationInfo;
609 
610   Info->Function = this;
611   Info->Template.setPointer(Template);
612   Info->Template.setInt(0); // Implicit instantiation, unless told otherwise
613   Info->TemplateArguments = TemplateArgs;
614   TemplateOrSpecialization = Info;
615 
616   // Insert this function template specialization into the set of known
617   // function template specialiations.
618   Template->getSpecializations().InsertNode(Info, InsertPos);
619 }
620 
621 bool FunctionDecl::isExplicitSpecialization() const {
622   // FIXME: check this property for explicit specializations of member
623   // functions of class templates.
624   FunctionTemplateSpecializationInfo *Info
625     = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>();
626   if (!Info)
627     return false;
628 
629   return Info->isExplicitSpecialization();
630 }
631 
632 void FunctionDecl::setExplicitSpecialization(bool ES) {
633   // FIXME: set this property for explicit specializations of member functions
634   // of class templates.
635   FunctionTemplateSpecializationInfo *Info
636     = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>();
637   if (Info)
638     Info->setExplicitSpecialization(ES);
639 }
640 
641 //===----------------------------------------------------------------------===//
642 // TagDecl Implementation
643 //===----------------------------------------------------------------------===//
644 
645 void TagDecl::startDefinition() {
646   TagType *TagT = const_cast<TagType *>(TypeForDecl->getAsTagType());
647   TagT->decl.setPointer(this);
648   TagT->getAsTagType()->decl.setInt(1);
649 }
650 
651 void TagDecl::completeDefinition() {
652   assert((!TypeForDecl ||
653           TypeForDecl->getAsTagType()->decl.getPointer() == this) &&
654          "Attempt to redefine a tag definition?");
655   IsDefinition = true;
656   TagType *TagT = const_cast<TagType *>(TypeForDecl->getAsTagType());
657   TagT->decl.setPointer(this);
658   TagT->decl.setInt(0);
659 }
660 
661 TagDecl* TagDecl::getDefinition(ASTContext& C) const {
662   QualType T = C.getTypeDeclType(const_cast<TagDecl*>(this));
663   TagDecl* D = cast<TagDecl>(T->getAsTagType()->getDecl());
664   return D->isDefinition() ? D : 0;
665 }
666 
667 //===----------------------------------------------------------------------===//
668 // RecordDecl Implementation
669 //===----------------------------------------------------------------------===//
670 
671 RecordDecl::RecordDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L,
672                        IdentifierInfo *Id)
673   : TagDecl(DK, TK, DC, L, Id) {
674   HasFlexibleArrayMember = false;
675   AnonymousStructOrUnion = false;
676   assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!");
677 }
678 
679 RecordDecl *RecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
680                                SourceLocation L, IdentifierInfo *Id,
681                                RecordDecl* PrevDecl) {
682 
683   RecordDecl* R = new (C) RecordDecl(Record, TK, DC, L, Id);
684   C.getTypeDeclType(R, PrevDecl);
685   return R;
686 }
687 
688 RecordDecl::~RecordDecl() {
689 }
690 
691 void RecordDecl::Destroy(ASTContext& C) {
692   TagDecl::Destroy(C);
693 }
694 
695 bool RecordDecl::isInjectedClassName() const {
696   return isImplicit() && getDeclName() && getDeclContext()->isRecord() &&
697     cast<RecordDecl>(getDeclContext())->getDeclName() == getDeclName();
698 }
699 
700 /// completeDefinition - Notes that the definition of this type is now
701 /// complete.
702 void RecordDecl::completeDefinition(ASTContext& C) {
703   assert(!isDefinition() && "Cannot redefine record!");
704   TagDecl::completeDefinition();
705 }
706 
707 //===----------------------------------------------------------------------===//
708 // BlockDecl Implementation
709 //===----------------------------------------------------------------------===//
710 
711 BlockDecl::~BlockDecl() {
712 }
713 
714 void BlockDecl::Destroy(ASTContext& C) {
715   if (Body)
716     Body->Destroy(C);
717 
718   for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I)
719     (*I)->Destroy(C);
720 
721   C.Deallocate(ParamInfo);
722   Decl::Destroy(C);
723 }
724 
725 void BlockDecl::setParams(ASTContext& C, ParmVarDecl **NewParamInfo,
726                           unsigned NParms) {
727   assert(ParamInfo == 0 && "Already has param info!");
728 
729   // Zero params -> null pointer.
730   if (NParms) {
731     NumParams = NParms;
732     void *Mem = C.Allocate(sizeof(ParmVarDecl*)*NumParams);
733     ParamInfo = new (Mem) ParmVarDecl*[NumParams];
734     memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams);
735   }
736 }
737 
738 unsigned BlockDecl::getNumParams() const {
739   return NumParams;
740 }
741