forked from OSchip/llvm-project
Introduce FunctionDecl::getLatestDeclaration() and VarDecl::getLatestDeclaration().
For multiple redeclarations they return the last one. Also, add some non const versions of methods. llvm-svn: 75603
This commit is contained in:
parent
ef17c07bf6
commit
0736c5ca3b
|
@ -248,7 +248,11 @@ private:
|
|||
bool DeclaredInCondition : 1;
|
||||
|
||||
/// \brief The previous declaration of this variable.
|
||||
VarDecl *PreviousDeclaration;
|
||||
///
|
||||
/// If the int part is 0, this is a link to the previous declaration.
|
||||
/// If the int part is 1, this is the first declaration and
|
||||
/// PreviousDeclaration points to the latest declaration.
|
||||
llvm::PointerIntPair<VarDecl *, 1> PreviousDeclaration;
|
||||
|
||||
// Move to DeclGroup when it is implemented.
|
||||
SourceLocation TypeSpecStartLoc;
|
||||
|
@ -258,7 +262,7 @@ protected:
|
|||
QualType T, StorageClass SC, SourceLocation TSSL = SourceLocation())
|
||||
: ValueDecl(DK, DC, L, Id, T), Init(),
|
||||
ThreadSpecified(false), HasCXXDirectInit(false),
|
||||
DeclaredInCondition(false), PreviousDeclaration(0),
|
||||
DeclaredInCondition(false), PreviousDeclaration(this, 1),
|
||||
TypeSpecStartLoc(TSSL) {
|
||||
SClass = SC;
|
||||
}
|
||||
|
@ -406,16 +410,32 @@ public:
|
|||
}
|
||||
|
||||
/// getPreviousDeclaration - Return the previous declaration of this
|
||||
/// variable.
|
||||
const VarDecl *getPreviousDeclaration() const { return PreviousDeclaration; }
|
||||
|
||||
void setPreviousDeclaration(VarDecl *PrevDecl) {
|
||||
PreviousDeclaration = PrevDecl;
|
||||
/// variable or NULL if this is the first declaration.
|
||||
VarDecl *getPreviousDeclaration() {
|
||||
if (PreviousDeclaration.getInt() == 0)
|
||||
return PreviousDeclaration.getPointer();
|
||||
return 0;
|
||||
}
|
||||
const VarDecl *getPreviousDeclaration() const {
|
||||
return const_cast<VarDecl *>(this)->getPreviousDeclaration();
|
||||
}
|
||||
|
||||
void setPreviousDeclaration(VarDecl *PrevDecl);
|
||||
|
||||
/// \brief For multiple redeclarations returns the first one, otherwise
|
||||
/// returns itself.
|
||||
const VarDecl *getFirstDeclaration() const;
|
||||
VarDecl *getFirstDeclaration();
|
||||
const VarDecl *getFirstDeclaration() const {
|
||||
return const_cast<VarDecl *>(this)->getFirstDeclaration();
|
||||
}
|
||||
|
||||
/// \brief For multiple redeclarations returns the latest, otherwise
|
||||
/// returns itself.
|
||||
const VarDecl *getLatestDeclaration() const {
|
||||
const VarDecl *First = getFirstDeclaration();
|
||||
assert(First->PreviousDeclaration.getInt() == 1 && "Expected first");
|
||||
return First->PreviousDeclaration.getPointer();
|
||||
}
|
||||
|
||||
virtual Decl *getPrimaryDecl() const;
|
||||
|
||||
|
@ -642,16 +662,19 @@ private:
|
|||
|
||||
LazyDeclStmtPtr Body;
|
||||
|
||||
/// PreviousDeclaration - A link to the previous declaration of this
|
||||
/// same function, NULL if this is the first declaration. For
|
||||
/// PreviousDeclaration - If the int part is 0, this is a link to the previous
|
||||
/// declaration of this same function. If the int part is 1, this is the first
|
||||
/// declaration and PreviousDeclaration points to the latest declaration. For
|
||||
/// example, in the following code, the PreviousDeclaration can be
|
||||
/// traversed several times to see all three declarations of the
|
||||
/// function "f", the last of which is also a definition.
|
||||
///
|
||||
/// int f(int x, int y = 1);
|
||||
/// int f(int x = 0, int y);
|
||||
/// int f(int x, int y) { return x + y; }
|
||||
FunctionDecl *PreviousDeclaration;
|
||||
/// #1 int f(int x, int y = 1); // <pointer to #3, 1>
|
||||
/// #2 int f(int x = 0, int y); // <pointer to #1, 0>
|
||||
/// #3 int f(int x, int y) { return x + y; } // <pointer to #2, 0>
|
||||
///
|
||||
/// If there is only one declaration, it is <pointer to self, 1>
|
||||
llvm::PointerIntPair<FunctionDecl *, 1> PreviousDeclaration;
|
||||
|
||||
// FIXME: This can be packed into the bitfields in Decl.
|
||||
// NOTE: VC++ treats enums as signed, avoid using the StorageClass enum
|
||||
|
@ -699,7 +722,7 @@ protected:
|
|||
SourceLocation TSSL = SourceLocation())
|
||||
: ValueDecl(DK, DC, L, N, T),
|
||||
DeclContext(DK),
|
||||
ParamInfo(0), Body(), PreviousDeclaration(0),
|
||||
ParamInfo(0), Body(), PreviousDeclaration(this, 1),
|
||||
SClass(S), IsInline(isInline), C99InlineDefinition(false),
|
||||
IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false),
|
||||
HasWrittenPrototype(true), IsDeleted(false), TypeSpecStartLoc(TSSL),
|
||||
|
@ -810,14 +833,30 @@ public:
|
|||
bool isGlobal() const;
|
||||
|
||||
/// getPreviousDeclaration - Return the previous declaration of this
|
||||
/// function.
|
||||
/// function or NULL if this is the first declaration.
|
||||
FunctionDecl *getPreviousDeclaration() {
|
||||
if (PreviousDeclaration.getInt() == 0)
|
||||
return PreviousDeclaration.getPointer();
|
||||
return 0;
|
||||
}
|
||||
const FunctionDecl *getPreviousDeclaration() const {
|
||||
return PreviousDeclaration;
|
||||
return const_cast<FunctionDecl *>(this)->getPreviousDeclaration();
|
||||
}
|
||||
|
||||
/// \brief For multiple redeclarations returns the first one, otherwise
|
||||
/// returns itself.
|
||||
const FunctionDecl *getFirstDeclaration() const;
|
||||
FunctionDecl *getFirstDeclaration();
|
||||
const FunctionDecl *getFirstDeclaration() const {
|
||||
return const_cast<FunctionDecl *>(this)->getFirstDeclaration();
|
||||
}
|
||||
|
||||
/// \brief For multiple redeclarations returns the latest, otherwise
|
||||
/// returns itself.
|
||||
const FunctionDecl *getLatestDeclaration() const {
|
||||
const FunctionDecl *First = getFirstDeclaration();
|
||||
assert(First->PreviousDeclaration.getInt() == 1 && "Expected first");
|
||||
return First->PreviousDeclaration.getPointer();
|
||||
}
|
||||
|
||||
void setPreviousDeclaration(FunctionDecl * PrevDecl);
|
||||
|
||||
|
|
|
@ -358,8 +358,25 @@ const Expr *VarDecl::getDefinition(const VarDecl *&Def) const {
|
|||
return Def? Def->getInit() : 0;
|
||||
}
|
||||
|
||||
const VarDecl *VarDecl::getFirstDeclaration() const {
|
||||
const VarDecl *First = this;
|
||||
void VarDecl::setPreviousDeclaration(VarDecl *PrevDecl) {
|
||||
if (PrevDecl) {
|
||||
// Point to previous.
|
||||
PreviousDeclaration.setPointer(PrevDecl);
|
||||
PreviousDeclaration.setInt(0);
|
||||
|
||||
// First one will point to this one as latest.
|
||||
VarDecl *First = PrevDecl->getFirstDeclaration();
|
||||
assert(First->PreviousDeclaration.getInt() == 1 && "Expected first");
|
||||
First->PreviousDeclaration.setPointer(this);
|
||||
} else {
|
||||
// This is first.
|
||||
PreviousDeclaration.setPointer(this);
|
||||
PreviousDeclaration.setInt(1);
|
||||
}
|
||||
}
|
||||
|
||||
VarDecl *VarDecl::getFirstDeclaration() {
|
||||
VarDecl *First = this;
|
||||
while (First->getPreviousDeclaration())
|
||||
First = First->getPreviousDeclaration();
|
||||
|
||||
|
@ -388,7 +405,8 @@ void FunctionDecl::Destroy(ASTContext& C) {
|
|||
|
||||
|
||||
Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const {
|
||||
for (const FunctionDecl *FD = this; FD != 0; FD = FD->PreviousDeclaration) {
|
||||
for (const FunctionDecl *FD = this;
|
||||
FD != 0; FD = FD->getPreviousDeclaration()) {
|
||||
if (FD->Body) {
|
||||
Definition = FD;
|
||||
return FD->Body.get(getASTContext().getExternalSource());
|
||||
|
@ -399,7 +417,8 @@ Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const {
|
|||
}
|
||||
|
||||
Stmt *FunctionDecl::getBodyIfAvailable() const {
|
||||
for (const FunctionDecl *FD = this; FD != 0; FD = FD->PreviousDeclaration) {
|
||||
for (const FunctionDecl *FD = this;
|
||||
FD != 0; FD = FD->getPreviousDeclaration()) {
|
||||
if (FD->Body && !FD->Body.isOffset()) {
|
||||
return FD->Body.get(0);
|
||||
}
|
||||
|
@ -571,7 +590,20 @@ bool FunctionDecl::isExternGNUInline(ASTContext &Context) const {
|
|||
|
||||
void
|
||||
FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
|
||||
PreviousDeclaration = PrevDecl;
|
||||
if (PrevDecl) {
|
||||
// Point to previous.
|
||||
PreviousDeclaration.setPointer(PrevDecl);
|
||||
PreviousDeclaration.setInt(0);
|
||||
|
||||
// First one will point to this one as latest.
|
||||
FunctionDecl *First = PrevDecl->getFirstDeclaration();
|
||||
assert(First->PreviousDeclaration.getInt() == 1 && "Expected first");
|
||||
First->PreviousDeclaration.setPointer(this);
|
||||
} else {
|
||||
// This is first.
|
||||
PreviousDeclaration.setPointer(this);
|
||||
PreviousDeclaration.setInt(1);
|
||||
}
|
||||
|
||||
if (FunctionTemplateDecl *FunTmpl = getDescribedFunctionTemplate()) {
|
||||
FunctionTemplateDecl *PrevFunTmpl
|
||||
|
@ -581,8 +613,8 @@ FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
|
|||
}
|
||||
}
|
||||
|
||||
const FunctionDecl *FunctionDecl::getFirstDeclaration() const {
|
||||
const FunctionDecl *First = this;
|
||||
FunctionDecl *FunctionDecl::getFirstDeclaration() {
|
||||
FunctionDecl *First = this;
|
||||
while (First->getPreviousDeclaration())
|
||||
First = First->getPreviousDeclaration();
|
||||
|
||||
|
|
Loading…
Reference in New Issue