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