mirror of
https://github.com/intel/llvm.git
synced 2026-01-28 00:15:21 +08:00
operator+, directly, using the same mechanism as all other special names. Removed the "special" identifiers for the overloaded operators from the identifier table and IdentifierInfo data structure. IdentifierInfo is back to representing only real identifiers. Added a new Action, ActOnOperatorFunctionIdExpr, that builds an expression from an parsed operator-function-id (e.g., "operator +"). ActOnIdentifierExpr used to do this job, but operator-function-ids are no longer represented by IdentifierInfo's. Extended Declarator to store overloaded operator names. Sema::GetNameForDeclarator now knows how to turn the operator name into a DeclarationName for the overloaded operator. Except for (perhaps) consolidating the functionality of ActOnIdentifier, ActOnOperatorFunctionIdExpr, and ActOnConversionFunctionExpr into a common routine that builds an appropriate DeclRefExpr by looking up a DeclarationName, all of the work on normalizing declaration names should be complete with this commit. llvm-svn: 59526
326 lines
11 KiB
C++
326 lines
11 KiB
C++
//===--- Decl.cpp - Declaration AST Node Implementation -------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements the Decl subclasses.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "clang/AST/Decl.h"
|
|
#include "clang/AST/ASTContext.h"
|
|
#include "clang/AST/Stmt.h"
|
|
#include "clang/Basic/IdentifierTable.h"
|
|
|
|
using namespace clang;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Decl Allocation/Deallocation Method Implementations
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) {
|
|
void *Mem = C.getAllocator().Allocate<TranslationUnitDecl>();
|
|
return new (Mem) TranslationUnitDecl();
|
|
}
|
|
|
|
NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC,
|
|
SourceLocation L, IdentifierInfo *Id) {
|
|
void *Mem = C.getAllocator().Allocate<NamespaceDecl>();
|
|
return new (Mem) NamespaceDecl(DC, L, Id);
|
|
}
|
|
|
|
void NamespaceDecl::Destroy(ASTContext& C) {
|
|
// NamespaceDecl uses "NextDeclarator" to chain namespace declarations
|
|
// together. They are all top-level Decls.
|
|
|
|
this->~NamespaceDecl();
|
|
C.getAllocator().Deallocate((void *)this);
|
|
}
|
|
|
|
|
|
ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC,
|
|
SourceLocation L, IdentifierInfo *Id, QualType T, ScopedDecl *PrevDecl) {
|
|
void *Mem = C.getAllocator().Allocate<ImplicitParamDecl>();
|
|
return new (Mem) ImplicitParamDecl(ImplicitParam, DC, L, Id, T, PrevDecl);
|
|
}
|
|
|
|
VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC,
|
|
SourceLocation L,
|
|
IdentifierInfo *Id, QualType T,
|
|
StorageClass S, ScopedDecl *PrevDecl,
|
|
SourceLocation TypeSpecStartLoc) {
|
|
void *Mem = C.getAllocator().Allocate<VarDecl>();
|
|
return new (Mem) VarDecl(Var, DC, L, Id, T, S, PrevDecl, TypeSpecStartLoc);
|
|
}
|
|
|
|
ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC,
|
|
SourceLocation L, IdentifierInfo *Id,
|
|
QualType T, StorageClass S,
|
|
Expr *DefArg, ScopedDecl *PrevDecl) {
|
|
void *Mem = C.getAllocator().Allocate<ParmVarDecl>();
|
|
return new (Mem) ParmVarDecl(DC, L, Id, T, S, DefArg, PrevDecl);
|
|
}
|
|
|
|
FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC,
|
|
SourceLocation L,
|
|
DeclarationName N, QualType T,
|
|
StorageClass S, bool isInline,
|
|
ScopedDecl *PrevDecl,
|
|
SourceLocation TypeSpecStartLoc) {
|
|
void *Mem = C.getAllocator().Allocate<FunctionDecl>();
|
|
return new (Mem) FunctionDecl(Function, DC, L, N, T, S, isInline, PrevDecl,
|
|
TypeSpecStartLoc);
|
|
}
|
|
|
|
BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) {
|
|
void *Mem = C.getAllocator().Allocate<BlockDecl>();
|
|
return new (Mem) BlockDecl(DC, L);
|
|
}
|
|
|
|
FieldDecl *FieldDecl::Create(ASTContext &C, SourceLocation L,
|
|
IdentifierInfo *Id, QualType T, Expr *BW) {
|
|
void *Mem = C.getAllocator().Allocate<FieldDecl>();
|
|
return new (Mem) FieldDecl(L, Id, T, BW);
|
|
}
|
|
|
|
|
|
EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD,
|
|
SourceLocation L,
|
|
IdentifierInfo *Id, QualType T,
|
|
Expr *E, const llvm::APSInt &V,
|
|
ScopedDecl *PrevDecl){
|
|
void *Mem = C.getAllocator().Allocate<EnumConstantDecl>();
|
|
return new (Mem) EnumConstantDecl(CD, L, Id, T, E, V, PrevDecl);
|
|
}
|
|
|
|
void EnumConstantDecl::Destroy(ASTContext& C) {
|
|
if (Init) Init->Destroy(C);
|
|
Decl::Destroy(C);
|
|
}
|
|
|
|
TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC,
|
|
SourceLocation L,
|
|
IdentifierInfo *Id, QualType T,
|
|
ScopedDecl *PD) {
|
|
void *Mem = C.getAllocator().Allocate<TypedefDecl>();
|
|
return new (Mem) TypedefDecl(DC, L, Id, T, PD);
|
|
}
|
|
|
|
EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
|
|
IdentifierInfo *Id,
|
|
ScopedDecl *PrevDecl) {
|
|
void *Mem = C.getAllocator().Allocate<EnumDecl>();
|
|
return new (Mem) EnumDecl(DC, L, Id, PrevDecl);
|
|
}
|
|
|
|
void EnumDecl::Destroy(ASTContext& C) {
|
|
if (getEnumConstantList()) getEnumConstantList()->Destroy(C);
|
|
Decl::Destroy(C);
|
|
}
|
|
|
|
FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C,
|
|
SourceLocation L,
|
|
StringLiteral *Str) {
|
|
void *Mem = C.getAllocator().Allocate<FileScopeAsmDecl>();
|
|
return new (Mem) FileScopeAsmDecl(L, Str);
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// ScopedDecl Implementation
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
void ScopedDecl::setLexicalDeclContext(DeclContext *DC) {
|
|
if (DC == getLexicalDeclContext())
|
|
return;
|
|
|
|
if (isInSemaDC()) {
|
|
MultipleDC *MDC = new MultipleDC();
|
|
MDC->SemanticDC = getDeclContext();
|
|
MDC->LexicalDC = DC;
|
|
DeclCtx = reinterpret_cast<uintptr_t>(MDC) | 0x1;
|
|
} else {
|
|
getMultipleDC()->LexicalDC = DC;
|
|
}
|
|
}
|
|
|
|
ScopedDecl::~ScopedDecl() {
|
|
if (isOutOfSemaDC())
|
|
delete getMultipleDC();
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// FunctionDecl Implementation
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
FunctionDecl::~FunctionDecl() {
|
|
delete[] ParamInfo;
|
|
}
|
|
|
|
void FunctionDecl::Destroy(ASTContext& C) {
|
|
if (Body)
|
|
Body->Destroy(C);
|
|
|
|
for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I)
|
|
(*I)->Destroy(C);
|
|
|
|
Decl::Destroy(C);
|
|
}
|
|
|
|
|
|
Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const {
|
|
for (const FunctionDecl *FD = this; FD != 0; FD = FD->PreviousDeclaration) {
|
|
if (FD->Body) {
|
|
Definition = FD;
|
|
return FD->Body;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Helper function for FunctionDecl::getNumParams and FunctionDecl::setParams()
|
|
static unsigned getNumTypeParams(QualType T) {
|
|
const FunctionType *FT = T->getAsFunctionType();
|
|
if (isa<FunctionTypeNoProto>(FT))
|
|
return 0;
|
|
return cast<FunctionTypeProto>(FT)->getNumArgs();
|
|
}
|
|
|
|
unsigned FunctionDecl::getNumParams() const {
|
|
// Can happen if a FunctionDecl is declared using typeof(some_other_func) bar;
|
|
if (!ParamInfo)
|
|
return 0;
|
|
|
|
return getNumTypeParams(getType());
|
|
}
|
|
|
|
void FunctionDecl::setParams(ParmVarDecl **NewParamInfo, unsigned NumParams) {
|
|
assert(ParamInfo == 0 && "Already has param info!");
|
|
assert(NumParams == getNumTypeParams(getType()) &&
|
|
"Parameter count mismatch!");
|
|
|
|
// Zero params -> null pointer.
|
|
if (NumParams) {
|
|
ParamInfo = new ParmVarDecl*[NumParams];
|
|
memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams);
|
|
}
|
|
}
|
|
|
|
/// getMinRequiredArguments - Returns the minimum number of arguments
|
|
/// needed to call this function. This may be fewer than the number of
|
|
/// function parameters, if some of the parameters have default
|
|
/// arguments (in C++).
|
|
unsigned FunctionDecl::getMinRequiredArguments() const {
|
|
unsigned NumRequiredArgs = getNumParams();
|
|
while (NumRequiredArgs > 0
|
|
&& getParamDecl(NumRequiredArgs-1)->getDefaultArg())
|
|
--NumRequiredArgs;
|
|
|
|
return NumRequiredArgs;
|
|
}
|
|
|
|
/// getOverloadedOperator - Which C++ overloaded operator this
|
|
/// function represents, if any.
|
|
OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const {
|
|
if (getDeclName().getNameKind() == DeclarationName::CXXOperatorName)
|
|
return getDeclName().getCXXOverloadedOperator();
|
|
else
|
|
return OO_None;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// TagdDecl Implementation
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
TagDecl* TagDecl::getDefinition(ASTContext& C) const {
|
|
QualType T = C.getTypeDeclType(const_cast<TagDecl*>(this));
|
|
TagDecl* D = cast<TagDecl>(cast<TagType>(T)->getDecl());
|
|
return D->isDefinition() ? D : 0;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// RecordDecl Implementation
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
RecordDecl::RecordDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L,
|
|
IdentifierInfo *Id)
|
|
: TagDecl(DK, TK, DC, L, Id, 0) {
|
|
|
|
HasFlexibleArrayMember = false;
|
|
assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!");
|
|
Members = 0;
|
|
NumMembers = -1;
|
|
}
|
|
|
|
RecordDecl *RecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
|
|
SourceLocation L, IdentifierInfo *Id,
|
|
RecordDecl* PrevDecl) {
|
|
|
|
void *Mem = C.getAllocator().Allocate<RecordDecl>();
|
|
RecordDecl* R = new (Mem) RecordDecl(Record, TK, DC, L, Id);
|
|
C.getTypeDeclType(R, PrevDecl);
|
|
return R;
|
|
}
|
|
|
|
RecordDecl::~RecordDecl() {
|
|
delete[] Members;
|
|
}
|
|
|
|
void RecordDecl::Destroy(ASTContext& C) {
|
|
if (isDefinition())
|
|
for (field_iterator I=field_begin(), E=field_end(); I!=E; ++I)
|
|
(*I)->Destroy(C);
|
|
|
|
TagDecl::Destroy(C);
|
|
}
|
|
|
|
/// defineBody - When created, RecordDecl's correspond to a forward declared
|
|
/// record. This method is used to mark the decl as being defined, with the
|
|
/// specified contents.
|
|
void RecordDecl::defineBody(ASTContext& C, FieldDecl **members,
|
|
unsigned numMembers) {
|
|
assert(!isDefinition() && "Cannot redefine record!");
|
|
setDefinition(true);
|
|
NumMembers = numMembers;
|
|
if (numMembers) {
|
|
Members = new FieldDecl*[numMembers];
|
|
memcpy(Members, members, numMembers*sizeof(Decl*));
|
|
}
|
|
|
|
// Let ASTContext know that this is the defining RecordDecl this type.
|
|
C.setTagDefinition(this);
|
|
}
|
|
|
|
|
|
FieldDecl *RecordDecl::getMember(IdentifierInfo *II) {
|
|
if (Members == 0 || NumMembers < 0)
|
|
return 0;
|
|
|
|
// Linear search. When C++ classes come along, will likely need to revisit.
|
|
for (int i = 0; i != NumMembers; ++i)
|
|
if (Members[i]->getIdentifier() == II)
|
|
return Members[i];
|
|
return 0;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// BlockDecl Implementation
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
BlockDecl::~BlockDecl() {
|
|
}
|
|
|
|
void BlockDecl::Destroy(ASTContext& C) {
|
|
if (Body)
|
|
Body->Destroy(C);
|
|
|
|
for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I)
|
|
(*I)->Destroy(C);
|
|
|
|
Decl::Destroy(C);
|
|
}
|