forked from OSchip/llvm-project
Introduce the Redeclarable template class, which serves as a base type defining the common interface for Decls that can be redeclared.
Make FunctionDecl and VarDecl use it. llvm-svn: 76297
This commit is contained in:
parent
194a9d8e73
commit
fad334ce5b
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "clang/AST/APValue.h"
|
||||
#include "clang/AST/DeclBase.h"
|
||||
#include "clang/AST/Redeclarable.h"
|
||||
#include "clang/AST/DeclarationName.h"
|
||||
#include "clang/AST/ExternalASTSource.h"
|
||||
|
||||
|
@ -224,7 +225,7 @@ struct EvaluatedStmt {
|
|||
|
||||
/// VarDecl - An instance of this class is created to represent a variable
|
||||
/// declaration or definition.
|
||||
class VarDecl : public ValueDecl {
|
||||
class VarDecl : public ValueDecl, public Redeclarable<VarDecl> {
|
||||
public:
|
||||
enum StorageClass {
|
||||
None, Auto, Register, Extern, Static, PrivateExtern
|
||||
|
@ -247,13 +248,6 @@ private:
|
|||
/// condition, e.g., if (int x = foo()) { ... }.
|
||||
bool DeclaredInCondition : 1;
|
||||
|
||||
/// \brief The previous declaration of this variable.
|
||||
///
|
||||
/// 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;
|
||||
friend class StmtIteratorBase;
|
||||
|
@ -262,8 +256,7 @@ protected:
|
|||
QualType T, StorageClass SC, SourceLocation TSSL = SourceLocation())
|
||||
: ValueDecl(DK, DC, L, Id, T), Init(),
|
||||
ThreadSpecified(false), HasCXXDirectInit(false),
|
||||
DeclaredInCondition(false), PreviousDeclaration(this, 1),
|
||||
TypeSpecStartLoc(TSSL) {
|
||||
DeclaredInCondition(false), TypeSpecStartLoc(TSSL) {
|
||||
SClass = SC;
|
||||
}
|
||||
public:
|
||||
|
@ -409,69 +402,8 @@ public:
|
|||
DeclaredInCondition = InCondition;
|
||||
}
|
||||
|
||||
/// getPreviousDeclaration - Return the previous declaration of this
|
||||
/// 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);
|
||||
|
||||
virtual VarDecl *getCanonicalDecl();
|
||||
|
||||
/// \brief Iterates through all the redeclarations of the same var decl.
|
||||
class redecl_iterator {
|
||||
/// Current - The current declaration.
|
||||
VarDecl *Current;
|
||||
VarDecl *Starter;
|
||||
|
||||
public:
|
||||
typedef VarDecl* value_type;
|
||||
typedef VarDecl* reference;
|
||||
typedef VarDecl* pointer;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
redecl_iterator() : Current(0) { }
|
||||
explicit redecl_iterator(VarDecl *C) : Current(C), Starter(C) { }
|
||||
|
||||
reference operator*() const { return Current; }
|
||||
pointer operator->() const { return Current; }
|
||||
|
||||
redecl_iterator& operator++() {
|
||||
assert(Current && "Advancing while iterator has reached end");
|
||||
// Get either previous decl or latest decl.
|
||||
VarDecl *Next = Current->PreviousDeclaration.getPointer();
|
||||
Current = (Next != Starter ? Next : 0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
redecl_iterator operator++(int) {
|
||||
redecl_iterator tmp(*this);
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
friend bool operator==(redecl_iterator x, redecl_iterator y) {
|
||||
return x.Current == y.Current;
|
||||
}
|
||||
friend bool operator!=(redecl_iterator x, redecl_iterator y) {
|
||||
return x.Current != y.Current;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Returns iterator for all the redeclarations of the same variable.
|
||||
/// It will iterate at least once (when this decl is the only one).
|
||||
redecl_iterator redecls_begin() const {
|
||||
return redecl_iterator(const_cast<VarDecl*>(this));
|
||||
}
|
||||
redecl_iterator redecls_end() const { return redecl_iterator(); }
|
||||
|
||||
/// hasLocalStorage - Returns true if a variable with function scope
|
||||
/// is a non-static local variable.
|
||||
bool hasLocalStorage() const {
|
||||
|
@ -681,7 +613,8 @@ public:
|
|||
/// contains all of the information known about the function. Other,
|
||||
/// previous declarations of the function are available via the
|
||||
/// getPreviousDeclaration() chain.
|
||||
class FunctionDecl : public ValueDecl, public DeclContext {
|
||||
class FunctionDecl : public ValueDecl, public DeclContext,
|
||||
public Redeclarable<FunctionDecl> {
|
||||
public:
|
||||
enum StorageClass {
|
||||
None, Extern, Static, PrivateExtern
|
||||
|
@ -694,20 +627,6 @@ private:
|
|||
ParmVarDecl **ParamInfo;
|
||||
|
||||
LazyDeclStmtPtr Body;
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// #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
|
||||
|
@ -755,7 +674,7 @@ protected:
|
|||
SourceLocation TSSL = SourceLocation())
|
||||
: ValueDecl(DK, DC, L, N, T),
|
||||
DeclContext(DK),
|
||||
ParamInfo(0), Body(), PreviousDeclaration(this, 1),
|
||||
ParamInfo(0), Body(),
|
||||
SClass(S), IsInline(isInline), C99InlineDefinition(false),
|
||||
IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false),
|
||||
HasWrittenPrototype(true), IsDeleted(false), TypeSpecStartLoc(TSSL),
|
||||
|
@ -865,69 +784,10 @@ public:
|
|||
/// \brief Determines whether this is a global function.
|
||||
bool isGlobal() const;
|
||||
|
||||
/// getPreviousDeclaration - Return the previous declaration of this
|
||||
/// 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 const_cast<FunctionDecl *>(this)->getPreviousDeclaration();
|
||||
}
|
||||
|
||||
void setPreviousDeclaration(FunctionDecl * PrevDecl);
|
||||
|
||||
virtual FunctionDecl *getCanonicalDecl();
|
||||
|
||||
/// \brief Iterates through all the redeclarations of the same function decl.
|
||||
class redecl_iterator {
|
||||
/// Current - The current declaration.
|
||||
FunctionDecl *Current;
|
||||
FunctionDecl *Starter;
|
||||
|
||||
public:
|
||||
typedef FunctionDecl* value_type;
|
||||
typedef FunctionDecl* reference;
|
||||
typedef FunctionDecl* pointer;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
redecl_iterator() : Current(0) { }
|
||||
explicit redecl_iterator(FunctionDecl *C) : Current(C), Starter(C) { }
|
||||
|
||||
reference operator*() const { return Current; }
|
||||
pointer operator->() const { return Current; }
|
||||
|
||||
redecl_iterator& operator++() {
|
||||
assert(Current && "Advancing while iterator has reached end");
|
||||
// Get either previous decl or latest decl.
|
||||
FunctionDecl *Next = Current->PreviousDeclaration.getPointer();
|
||||
Current = (Next != Starter ? Next : 0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
redecl_iterator operator++(int) {
|
||||
redecl_iterator tmp(*this);
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
friend bool operator==(redecl_iterator x, redecl_iterator y) {
|
||||
return x.Current == y.Current;
|
||||
}
|
||||
friend bool operator!=(redecl_iterator x, redecl_iterator y) {
|
||||
return x.Current != y.Current;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Returns iterator for all the redeclarations of the same function
|
||||
/// decl. It will iterate at least once (when this decl is the only one).
|
||||
redecl_iterator redecls_begin() const {
|
||||
return redecl_iterator(const_cast<FunctionDecl*>(this));
|
||||
}
|
||||
redecl_iterator redecls_end() const { return redecl_iterator(); }
|
||||
|
||||
unsigned getBuiltinID(ASTContext &Context) const;
|
||||
|
||||
unsigned getNumParmVarDeclsFromType() const;
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
//===-- Redeclarable.h - Base for Decls that can be redeclared -*- C++ -*-====//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the Redeclarable interface.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_AST_REDECLARABLE_H
|
||||
#define LLVM_CLANG_AST_REDECLARABLE_H
|
||||
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
/// \brief Provides common interface for the Decls that can be redeclared.
|
||||
template<typename decl_type>
|
||||
class Redeclarable {
|
||||
|
||||
protected:
|
||||
struct DeclLink : public llvm::PointerIntPair<decl_type *, 1, bool> {
|
||||
DeclLink(decl_type *D, bool isLatest)
|
||||
: llvm::PointerIntPair<decl_type *, 1, bool>(D, isLatest) { }
|
||||
|
||||
typedef llvm::PointerIntPair<decl_type *, 1, bool> base_type;
|
||||
|
||||
bool NextIsPrevious() const { return base_type::getInt() == false; }
|
||||
bool NextIsLatest() const { return base_type::getInt() == true; }
|
||||
decl_type *getNext() const { return base_type::getPointer(); }
|
||||
};
|
||||
|
||||
struct PreviousDeclLink : public DeclLink {
|
||||
PreviousDeclLink(decl_type *D) : DeclLink(D, false) { }
|
||||
};
|
||||
|
||||
struct LatestDeclLink : public DeclLink {
|
||||
LatestDeclLink(decl_type *D) : DeclLink(D, true) { }
|
||||
};
|
||||
|
||||
/// \brief Points to the next redeclaration in the chain.
|
||||
///
|
||||
/// If NextIsPrevious() is true, this is a link to the previous declaration
|
||||
/// of this same Decl. If NextIsLatest() is true, this is the first
|
||||
/// declaration and Link points to the latest declaration. For example:
|
||||
///
|
||||
/// #1 int f(int x, int y = 1); // <pointer to #3, true>
|
||||
/// #2 int f(int x = 0, int y); // <pointer to #1, false>
|
||||
/// #3 int f(int x, int y) { return x + y; } // <pointer to #2, false>
|
||||
///
|
||||
/// If there is only one declaration, it is <pointer to self, true>
|
||||
DeclLink RedeclLink;
|
||||
|
||||
public:
|
||||
Redeclarable() : RedeclLink(LatestDeclLink(static_cast<decl_type*>(this))) { }
|
||||
|
||||
/// \brief Return the previous declaration of this declaration or NULL if this
|
||||
/// is the first declaration.
|
||||
decl_type *getPreviousDeclaration() {
|
||||
if (RedeclLink.NextIsPrevious())
|
||||
return RedeclLink.getNext();
|
||||
return 0;
|
||||
}
|
||||
const decl_type *getPreviousDeclaration() const {
|
||||
return const_cast<decl_type *>(
|
||||
static_cast<const decl_type*>(this))->getPreviousDeclaration();
|
||||
}
|
||||
|
||||
/// \brief Return the first declaration of this declaration or itself if this
|
||||
/// is the only declaration.
|
||||
decl_type *getFirstDeclaration() {
|
||||
decl_type *D = static_cast<decl_type*>(this);
|
||||
while (D->getPreviousDeclaration())
|
||||
D = D->getPreviousDeclaration();
|
||||
return D;
|
||||
}
|
||||
|
||||
/// \brief Set the previous declaration. If PrevDecl is NULL, set this as the
|
||||
/// first and only declaration.
|
||||
void setPreviousDeclaration(decl_type *PrevDecl) {
|
||||
decl_type *First;
|
||||
|
||||
if (PrevDecl) {
|
||||
// Point to previous.
|
||||
RedeclLink = PreviousDeclLink(PrevDecl);
|
||||
First = PrevDecl->getFirstDeclaration();
|
||||
assert(First->RedeclLink.NextIsLatest() && "Expected first");
|
||||
} else {
|
||||
// Make this first.
|
||||
First = static_cast<decl_type*>(this);
|
||||
}
|
||||
|
||||
// First one will point to this one as latest.
|
||||
First->RedeclLink = LatestDeclLink(static_cast<decl_type*>(this));
|
||||
}
|
||||
|
||||
/// \brief Iterates through all the redeclarations of the same decl.
|
||||
class redecl_iterator {
|
||||
/// Current - The current declaration.
|
||||
decl_type *Current;
|
||||
decl_type *Starter;
|
||||
|
||||
public:
|
||||
typedef decl_type* value_type;
|
||||
typedef decl_type* reference;
|
||||
typedef decl_type* pointer;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
redecl_iterator() : Current(0) { }
|
||||
explicit redecl_iterator(decl_type *C) : Current(C), Starter(C) { }
|
||||
|
||||
reference operator*() const { return Current; }
|
||||
pointer operator->() const { return Current; }
|
||||
|
||||
redecl_iterator& operator++() {
|
||||
assert(Current && "Advancing while iterator has reached end");
|
||||
// Get either previous decl or latest decl.
|
||||
decl_type *Next = Current->RedeclLink.getNext();
|
||||
Current = (Next != Starter ? Next : 0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
redecl_iterator operator++(int) {
|
||||
redecl_iterator tmp(*this);
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
friend bool operator==(redecl_iterator x, redecl_iterator y) {
|
||||
return x.Current == y.Current;
|
||||
}
|
||||
friend bool operator!=(redecl_iterator x, redecl_iterator y) {
|
||||
return x.Current != y.Current;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Returns iterator for all the redeclarations of the same decl.
|
||||
/// It will iterate at least once (when this decl is the only one).
|
||||
redecl_iterator redecls_begin() const {
|
||||
return redecl_iterator(const_cast<decl_type*>(
|
||||
static_cast<const decl_type*>(this)));
|
||||
}
|
||||
redecl_iterator redecls_end() const { return redecl_iterator(); }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -362,29 +362,8 @@ const Expr *VarDecl::getDefinition(const VarDecl *&Def) const {
|
|||
return 0;
|
||||
}
|
||||
|
||||
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.
|
||||
// getCanonicalDecl returns the first one.
|
||||
VarDecl *First = PrevDecl->getCanonicalDecl();
|
||||
assert(First->PreviousDeclaration.getInt() == 1 && "Expected first");
|
||||
First->PreviousDeclaration.setPointer(this);
|
||||
} else {
|
||||
// This is first.
|
||||
PreviousDeclaration.setPointer(this);
|
||||
PreviousDeclaration.setInt(1);
|
||||
}
|
||||
}
|
||||
|
||||
VarDecl *VarDecl::getCanonicalDecl() {
|
||||
VarDecl *Var = this;
|
||||
while (Var->getPreviousDeclaration())
|
||||
Var = Var->getPreviousDeclaration();
|
||||
return Var;
|
||||
return getFirstDeclaration();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -586,22 +565,8 @@ bool FunctionDecl::isExternGNUInline(ASTContext &Context) const {
|
|||
|
||||
void
|
||||
FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
|
||||
if (PrevDecl) {
|
||||
// Point to previous.
|
||||
PreviousDeclaration.setPointer(PrevDecl);
|
||||
PreviousDeclaration.setInt(0);
|
||||
|
||||
// First one will point to this one as latest.
|
||||
// getCanonicalDecl returns the first one.
|
||||
FunctionDecl *First = PrevDecl->getCanonicalDecl();
|
||||
assert(First->PreviousDeclaration.getInt() == 1 && "Expected first");
|
||||
First->PreviousDeclaration.setPointer(this);
|
||||
} else {
|
||||
// This is first.
|
||||
PreviousDeclaration.setPointer(this);
|
||||
PreviousDeclaration.setInt(1);
|
||||
}
|
||||
|
||||
Redeclarable<FunctionDecl>::setPreviousDeclaration(PrevDecl);
|
||||
|
||||
if (FunctionTemplateDecl *FunTmpl = getDescribedFunctionTemplate()) {
|
||||
FunctionTemplateDecl *PrevFunTmpl
|
||||
= PrevDecl? PrevDecl->getDescribedFunctionTemplate() : 0;
|
||||
|
@ -611,10 +576,7 @@ FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
|
|||
}
|
||||
|
||||
FunctionDecl *FunctionDecl::getCanonicalDecl() {
|
||||
FunctionDecl *FD = this;
|
||||
while (FD->getPreviousDeclaration())
|
||||
FD = FD->getPreviousDeclaration();
|
||||
return FD;
|
||||
return getFirstDeclaration();
|
||||
}
|
||||
|
||||
/// getOverloadedOperator - Which C++ overloaded operator this
|
||||
|
|
Loading…
Reference in New Issue