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;
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;
}
}
/// 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;
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
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),
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);
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();
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());
}
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);
}
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
}
}
-const FunctionDecl *FunctionDecl::getFirstDeclaration() const {
- const FunctionDecl *First = this;
+FunctionDecl *FunctionDecl::getFirstDeclaration() {
+ FunctionDecl *First = this;
while (First->getPreviousDeclaration())
First = First->getPreviousDeclaration();