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