Decl.cpp revision 7a7be65a7801addae8205fd68323cecd70df1635
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/ASTContext.h"
17#include "clang/AST/Stmt.h"
18#include "clang/AST/Expr.h"
19#include "clang/Basic/IdentifierTable.h"
20
21using namespace clang;
22
23//===----------------------------------------------------------------------===//
24// Decl Allocation/Deallocation Method Implementations
25//===----------------------------------------------------------------------===//
26
27TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) {
28  return new (C) TranslationUnitDecl();
29}
30
31NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC,
32                                     SourceLocation L, IdentifierInfo *Id) {
33  return new (C) NamespaceDecl(DC, L, Id);
34}
35
36void NamespaceDecl::Destroy(ASTContext& C) {
37  // NamespaceDecl uses "NextDeclarator" to chain namespace declarations
38  // together. They are all top-level Decls.
39
40  this->~NamespaceDecl();
41  C.Deallocate((void *)this);
42}
43
44
45ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC,
46    SourceLocation L, IdentifierInfo *Id, QualType T) {
47  return new (C) ImplicitParamDecl(ImplicitParam, DC, L, Id, T);
48}
49
50ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC,
51                                 SourceLocation L, IdentifierInfo *Id,
52                                 QualType T, StorageClass S,
53                                 Expr *DefArg) {
54  return new (C) ParmVarDecl(ParmVar, DC, L, Id, T, S, DefArg);
55}
56
57QualType ParmVarDecl::getOriginalType() const {
58  if (const OriginalParmVarDecl *PVD =
59      dyn_cast<OriginalParmVarDecl>(this))
60    return PVD->OriginalType;
61  return getType();
62}
63
64OriginalParmVarDecl *OriginalParmVarDecl::Create(
65                                 ASTContext &C, DeclContext *DC,
66                                 SourceLocation L, IdentifierInfo *Id,
67                                 QualType T, QualType OT, StorageClass S,
68                                 Expr *DefArg) {
69  return new (C) OriginalParmVarDecl(DC, L, Id, T, OT, S, DefArg);
70}
71
72FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC,
73                                   SourceLocation L,
74                                   DeclarationName N, QualType T,
75                                   StorageClass S, bool isInline,
76                                   SourceLocation TypeSpecStartLoc) {
77  return new (C) FunctionDecl(Function, DC, L, N, T, S, isInline,
78                                TypeSpecStartLoc);
79}
80
81BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) {
82  return new (C) BlockDecl(DC, L);
83}
84
85FieldDecl *FieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
86                             IdentifierInfo *Id, QualType T, Expr *BW,
87                             bool Mutable) {
88  return new (C) FieldDecl(Decl::Field, DC, L, Id, T, BW, Mutable);
89}
90
91bool FieldDecl::isAnonymousStructOrUnion() const {
92  if (!isImplicit() || getDeclName())
93    return false;
94
95  if (const RecordType *Record = getType()->getAsRecordType())
96    return Record->getDecl()->isAnonymousStructOrUnion();
97
98  return false;
99}
100
101EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD,
102                                           SourceLocation L,
103                                           IdentifierInfo *Id, QualType T,
104                                           Expr *E, const llvm::APSInt &V) {
105  return new (C) EnumConstantDecl(CD, L, Id, T, E, V);
106}
107
108void EnumConstantDecl::Destroy(ASTContext& C) {
109  if (Init) Init->Destroy(C);
110  Decl::Destroy(C);
111}
112
113TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC,
114                                 SourceLocation L,
115                                 IdentifierInfo *Id, QualType T) {
116  return new (C) TypedefDecl(DC, L, Id, T);
117}
118
119EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
120                           IdentifierInfo *Id,
121                           EnumDecl *PrevDecl) {
122  EnumDecl *Enum = new (C) EnumDecl(DC, L, Id);
123  C.getTypeDeclType(Enum, PrevDecl);
124  return Enum;
125}
126
127void EnumDecl::Destroy(ASTContext& C) {
128  Decl::Destroy(C);
129}
130
131void EnumDecl::completeDefinition(ASTContext &C, QualType NewType) {
132  assert(!isDefinition() && "Cannot redefine enums!");
133  IntegerType = NewType;
134  TagDecl::completeDefinition();
135}
136
137FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC,
138                                           SourceLocation L,
139                                           StringLiteral *Str) {
140  return new (C) FileScopeAsmDecl(DC, L, Str);
141}
142
143//===----------------------------------------------------------------------===//
144// NamedDecl Implementation
145//===----------------------------------------------------------------------===//
146
147bool NamedDecl::declarationReplaces(NamedDecl *OldD) const {
148  assert(getDeclName() == OldD->getDeclName() && "Declaration name mismatch");
149
150  // UsingDirectiveDecl's are not really NamedDecl's, and all have same name.
151  // We want to keep it, unless it nominates same namespace.
152  if (getKind() == Decl::UsingDirective) {
153    return cast<UsingDirectiveDecl>(this)->getNominatedNamespace() ==
154           cast<UsingDirectiveDecl>(OldD)->getNominatedNamespace();
155  }
156
157  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this))
158    // For function declarations, we keep track of redeclarations.
159    return FD->getPreviousDeclaration() == OldD;
160
161  // For non-function declarations, if the declarations are of the
162  // same kind then this must be a redeclaration, or semantic analysis
163  // would not have given us the new declaration.
164  return this->getKind() == OldD->getKind();
165}
166
167
168//===----------------------------------------------------------------------===//
169// VarDecl Implementation
170//===----------------------------------------------------------------------===//
171
172VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
173                         IdentifierInfo *Id, QualType T, StorageClass S,
174                         SourceLocation TypeSpecStartLoc) {
175  return new (C) VarDecl(Var, DC, L, Id, T, S, TypeSpecStartLoc);
176}
177
178void VarDecl::Destroy(ASTContext& C) {
179  this->~VarDecl();
180  C.Deallocate((void *)this);
181}
182
183VarDecl::~VarDecl() {
184  delete getInit();
185}
186
187//===----------------------------------------------------------------------===//
188// FunctionDecl Implementation
189//===----------------------------------------------------------------------===//
190
191void FunctionDecl::Destroy(ASTContext& C) {
192  if (Body)
193    Body->Destroy(C);
194
195  for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I)
196    (*I)->Destroy(C);
197
198  C.Deallocate(ParamInfo);
199
200  Decl::Destroy(C);
201}
202
203
204Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const {
205  for (const FunctionDecl *FD = this; FD != 0; FD = FD->PreviousDeclaration) {
206    if (FD->Body) {
207      Definition = FD;
208      return FD->Body;
209    }
210  }
211
212  return 0;
213}
214
215// Helper function for FunctionDecl::getNumParams and FunctionDecl::setParams()
216static unsigned getNumTypeParams(QualType T) {
217  const FunctionType *FT = T->getAsFunctionType();
218  if (isa<FunctionTypeNoProto>(FT))
219    return 0;
220  return cast<FunctionTypeProto>(FT)->getNumArgs();
221}
222
223unsigned FunctionDecl::getNumParams() const {
224  // Can happen if a FunctionDecl is declared using typeof(some_other_func) bar;
225  if (!ParamInfo)
226    return 0;
227
228  return getNumTypeParams(getType());
229}
230
231void FunctionDecl::setParams(ASTContext& C, ParmVarDecl **NewParamInfo,
232                             unsigned NumParams) {
233  assert(ParamInfo == 0 && "Already has param info!");
234  assert(NumParams == getNumTypeParams(getType()) &&
235         "Parameter count mismatch!");
236
237  // Zero params -> null pointer.
238  if (NumParams) {
239    void *Mem = C.Allocate(sizeof(ParmVarDecl*)*NumParams);
240    ParamInfo = new (Mem) ParmVarDecl*[NumParams];
241    memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams);
242  }
243}
244
245/// getMinRequiredArguments - Returns the minimum number of arguments
246/// needed to call this function. This may be fewer than the number of
247/// function parameters, if some of the parameters have default
248/// arguments (in C++).
249unsigned FunctionDecl::getMinRequiredArguments() const {
250  unsigned NumRequiredArgs = getNumParams();
251  while (NumRequiredArgs > 0
252         && getParamDecl(NumRequiredArgs-1)->getDefaultArg())
253    --NumRequiredArgs;
254
255  return NumRequiredArgs;
256}
257
258/// getOverloadedOperator - Which C++ overloaded operator this
259/// function represents, if any.
260OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const {
261  if (getDeclName().getNameKind() == DeclarationName::CXXOperatorName)
262    return getDeclName().getCXXOverloadedOperator();
263  else
264    return OO_None;
265}
266
267//===----------------------------------------------------------------------===//
268// TagDecl Implementation
269//===----------------------------------------------------------------------===//
270
271void TagDecl::startDefinition() {
272  cast<TagType>(TypeForDecl)->decl.setPointer(this);
273  cast<TagType>(TypeForDecl)->decl.setInt(1);
274}
275
276void TagDecl::completeDefinition() {
277  assert((!TypeForDecl ||
278          cast<TagType>(TypeForDecl)->decl.getPointer() == this) &&
279         "Attempt to redefine a tag definition?");
280  IsDefinition = true;
281  cast<TagType>(TypeForDecl)->decl.setPointer(this);
282  cast<TagType>(TypeForDecl)->decl.setInt(0);
283}
284
285TagDecl* TagDecl::getDefinition(ASTContext& C) const {
286  QualType T = C.getTypeDeclType(const_cast<TagDecl*>(this));
287  TagDecl* D = cast<TagDecl>(cast<TagType>(T)->getDecl());
288  return D->isDefinition() ? D : 0;
289}
290
291//===----------------------------------------------------------------------===//
292// RecordDecl Implementation
293//===----------------------------------------------------------------------===//
294
295RecordDecl::RecordDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L,
296                       IdentifierInfo *Id)
297  : TagDecl(DK, TK, DC, L, Id) {
298  HasFlexibleArrayMember = false;
299  AnonymousStructOrUnion = false;
300  assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!");
301}
302
303RecordDecl *RecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
304                               SourceLocation L, IdentifierInfo *Id,
305                               RecordDecl* PrevDecl) {
306
307  RecordDecl* R = new (C) RecordDecl(Record, TK, DC, L, Id);
308  C.getTypeDeclType(R, PrevDecl);
309  return R;
310}
311
312RecordDecl::~RecordDecl() {
313}
314
315void RecordDecl::Destroy(ASTContext& C) {
316  TagDecl::Destroy(C);
317}
318
319/// completeDefinition - Notes that the definition of this type is now
320/// complete.
321void RecordDecl::completeDefinition(ASTContext& C) {
322  assert(!isDefinition() && "Cannot redefine record!");
323  TagDecl::completeDefinition();
324}
325
326//===----------------------------------------------------------------------===//
327// BlockDecl Implementation
328//===----------------------------------------------------------------------===//
329
330BlockDecl::~BlockDecl() {
331}
332
333void BlockDecl::Destroy(ASTContext& C) {
334  if (Body)
335    Body->Destroy(C);
336
337  for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I)
338    (*I)->Destroy(C);
339
340  Decl::Destroy(C);
341}
342