aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/Decl.h18
-rw-r--r--include/clang/AST/DeclBase.h58
-rw-r--r--include/clang/Basic/DiagnosticKinds.def2
-rw-r--r--lib/AST/DeclBase.cpp13
-rw-r--r--lib/AST/DeclSerialization.cpp7
-rw-r--r--lib/Sema/SemaDecl.cpp5
-rw-r--r--lib/Sema/SemaDeclObjC.cpp10
-rw-r--r--test/Sema/typedef-redef.c4
8 files changed, 93 insertions, 24 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 96bd8842b3..7392af6ca5 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -115,6 +115,17 @@ class ScopedDecl : public NamedDecl {
/// such as "int X, Y, *Z;" this indicates Decl for the next declarator.
ScopedDecl *NextDeclarator;
+ /// NextDeclInScope - The next declaration within the same lexical
+ /// DeclContext. These pointers form the linked list that is
+ /// traversed via DeclContext's decls_begin()/decls_end().
+ /// FIXME: If NextDeclarator is non-NULL, will it always be the same
+ /// as NextDeclInScope? If so, we can use a
+ /// PointerIntPair<ScopedDecl*, 1> to make ScopedDecl smaller.
+ ScopedDecl *NextDeclInScope;
+
+ friend class DeclContext;
+ friend class DeclContext::decl_iterator;
+
/// DeclCtx - Holds either a DeclContext* or a MultipleDC*.
/// For declarations that don't contain C++ scope specifiers, it contains
/// the DeclContext where the ScopedDecl was declared.
@@ -144,7 +155,7 @@ class ScopedDecl : public NamedDecl {
protected:
ScopedDecl(Kind DK, DeclContext *DC, SourceLocation L,
DeclarationName N, ScopedDecl *PrevDecl = 0)
- : NamedDecl(DK, L, N), NextDeclarator(PrevDecl),
+ : NamedDecl(DK, L, N), NextDeclarator(PrevDecl), NextDeclInScope(0),
DeclCtx(reinterpret_cast<uintptr_t>(DC)) {}
virtual ~ScopedDecl();
@@ -1215,6 +1226,11 @@ protected:
friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
};
+inline DeclContext::decl_iterator& DeclContext::decl_iterator::operator++() {
+ Current = Current->NextDeclInScope;
+ return *this;
+}
+
} // end namespace clang
#endif
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index c6a18a23ca..f96909bb91 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -18,7 +18,6 @@
#include "clang/AST/Type.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/PointerIntPair.h"
-#include <vector>
namespace clang {
class DeclContext;
@@ -307,9 +306,15 @@ class DeclContext {
/// FIXME: We need a better data structure for this.
llvm::PointerIntPair<void*, 3> LookupPtr;
- /// Decls - Contains all of the declarations that are defined inside
- /// this declaration context.
- std::vector<ScopedDecl*> Decls;
+ /// FirstDecl - The first declaration stored within this declaration
+ /// context.
+ ScopedDecl *FirstDecl;
+
+ /// LastDecl - The last declaration stored within this declaration
+ /// context. FIXME: We could probably cache this value somewhere
+ /// outside of the DeclContext, to reduce the size of DeclContext by
+ /// another pointer.
+ ScopedDecl *LastDecl;
// Used in the CastTo template to get the DeclKind
// from a Decl or a DeclContext. DeclContext doesn't have a getKind() method
@@ -363,8 +368,8 @@ class DeclContext {
bool isLookupMap() const { return LookupPtr.getInt() == LookupIsMap; }
protected:
- DeclContext(Decl::Kind K) : DeclKind(K), LookupPtr() {
- }
+ DeclContext(Decl::Kind K)
+ : DeclKind(K), LookupPtr(), FirstDecl(0), LastDecl(0) { }
void DestroyDecls(ASTContext &C);
@@ -483,12 +488,43 @@ public:
/// decl_iterator - Iterates through the declarations stored
/// within this context.
- typedef std::vector<ScopedDecl*>::const_iterator decl_iterator;
+ class decl_iterator {
+ /// Current - The current declaration.
+ ScopedDecl *Current;
+
+ public:
+ typedef ScopedDecl* value_type;
+ typedef ScopedDecl* reference;
+ typedef ScopedDecl* pointer;
+ typedef std::forward_iterator_tag iterator_category;
+ typedef std::ptrdiff_t difference_type;
+
+ decl_iterator() : Current(0) { }
+ explicit decl_iterator(ScopedDecl *C) : Current(C) { }
+
+ reference operator*() const { return Current; }
+ pointer operator->() const { return Current; }
+
+ decl_iterator& operator++();
+
+ decl_iterator operator++(int) {
+ decl_iterator tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+
+ friend bool operator==(decl_iterator x, decl_iterator y) {
+ return x.Current == y.Current;
+ }
+ friend bool operator!=(decl_iterator x, decl_iterator y) {
+ return x.Current != y.Current;
+ }
+ };
/// decls_begin/decls_end - Iterate over the declarations stored in
/// this context.
- decl_iterator decls_begin() const { return Decls.begin(); }
- decl_iterator decls_end() const { return Decls.end(); }
+ decl_iterator decls_begin() const { return decl_iterator(FirstDecl); }
+ decl_iterator decls_end() const { return decl_iterator(); }
/// specific_decl_iterator - Iterates over a subrange of
/// declarations stored in a DeclContext, providing only those that
@@ -548,8 +584,8 @@ public:
SkipToNextDecl();
}
- reference operator*() { return cast<SpecificDecl>(*Current); }
- pointer operator->() { return cast<SpecificDecl>(*Current); }
+ reference operator*() const { return cast<SpecificDecl>(*Current); }
+ pointer operator->() const { return cast<SpecificDecl>(*Current); }
specific_decl_iterator& operator++() {
++Current;
diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def
index 2577e65d3b..af721a6128 100644
--- a/include/clang/Basic/DiagnosticKinds.def
+++ b/include/clang/Basic/DiagnosticKinds.def
@@ -1003,6 +1003,8 @@ DIAG(err_static_non_static, ERROR,
"static declaration of %0 follows non-static declaration")
DIAG(err_non_static_static, ERROR,
"non-static declaration of %0 follows static declaration")
+DIAG(err_redefinition_different_type, ERROR,
+ "redefinition of %0 with a different type")
DIAG(err_redefinition_different_kind, ERROR,
"redefinition of %0 as different kind of symbol")
DIAG(err_redefinition_different_typedef, ERROR,
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index d9765ac4b4..cafe5358d6 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -401,7 +401,8 @@ DeclContext::~DeclContext() {
}
void DeclContext::DestroyDecls(ASTContext &C) {
- for (decl_iterator D = Decls.begin(); D != Decls.end(); ++D) {
+ for (decl_iterator D = decls_begin(); D != decls_end(); ++D) {
+ // FIXME: assert that this condition holds.
if ((*D)->getLexicalDeclContext() == this)
(*D)->Destroy(C);
}
@@ -515,7 +516,15 @@ DeclContext *DeclContext::getNextContext() {
void DeclContext::addDecl(ASTContext &Context, ScopedDecl *D, bool AllowLookup) {
assert(D->getLexicalDeclContext() == this && "Decl inserted into wrong lexical context");
- Decls.push_back(D);
+ assert(!D->NextDeclInScope && D != LastDecl &&
+ "Decl already inserted into a DeclContext");
+
+ if (FirstDecl) {
+ LastDecl->NextDeclInScope = D;
+ LastDecl = D;
+ } else {
+ FirstDecl = LastDecl = D;
+ }
if (AllowLookup)
D->getDeclContext()->insert(Context, D);
}
diff --git a/lib/AST/DeclSerialization.cpp b/lib/AST/DeclSerialization.cpp
index 38af462091..11577cd6dc 100644
--- a/lib/AST/DeclSerialization.cpp
+++ b/lib/AST/DeclSerialization.cpp
@@ -124,6 +124,9 @@ void Decl::ReadInRec(Deserializer& D, ASTContext& C) {
//===----------------------------------------------------------------------===//
void DeclContext::EmitOutRec(Serializer& S) const {
+#if 0
+ // FIXME: it would be far easier to just serialize FirstDecl and let
+ // ScopedDecl do the work of serializing NextDeclInScope.
S.EmitInt(Decls.size());
for (decl_iterator D = decls_begin(); D != decls_end(); ++D) {
bool Owned = ((*D)->getLexicalDeclContext() == this &&
@@ -135,9 +138,12 @@ void DeclContext::EmitOutRec(Serializer& S) const {
else
S.EmitPtr(*D);
}
+#endif
}
void DeclContext::ReadOutRec(Deserializer& D, ASTContext& C) {
+#if 0
+ // FIXME: See comment in DeclContext::EmitOutRec
unsigned NumDecls = D.ReadInt();
Decls.resize(NumDecls);
for (unsigned Idx = 0; Idx < NumDecls; ++Idx) {
@@ -147,6 +153,7 @@ void DeclContext::ReadOutRec(Deserializer& D, ASTContext& C) {
else
D.ReadPtr<ScopedDecl>(Decls[Idx]);
}
+#endif
}
//===----------------------------------------------------------------------===//
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index ecf6de9d96..ee72a98295 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -515,7 +515,7 @@ TypedefDecl *Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
Diag(New->getLocation(), diag::err_redefinition_different_typedef)
<< New->getUnderlyingType() << Old->getUnderlyingType();
Diag(Old->getLocation(), diag::note_previous_definition);
- return Old;
+ return New;
}
if (getLangOptions().Microsoft) return New;
@@ -768,7 +768,8 @@ VarDecl *Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
QualType OldCType = Context.getCanonicalType(Old->getType());
QualType NewCType = Context.getCanonicalType(New->getType());
if (OldCType != NewCType && !Context.typesAreCompatible(OldCType, NewCType)) {
- Diag(New->getLocation(), diag::err_redefinition) << New->getDeclName();
+ Diag(New->getLocation(), diag::err_redefinition_different_type)
+ << New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
return New;
}
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index f39b84c270..49a8c835c5 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -1078,6 +1078,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
ObjCPropertyDecl::Optional) ?
ObjCMethodDecl::Optional :
ObjCMethodDecl::Required);
+ CD->addDecl(Context, GetterMethod);
} else
// A user declared getter will be synthesize when @synthesize of
// the property with the same name is seen in the @implementation
@@ -1108,6 +1109,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
VarDecl::None,
0, 0);
SetterMethod->setMethodParams(&Argument, 1);
+ CD->addDecl(Context, SetterMethod);
} else
// A user declared setter will be synthesize when @synthesize of
// the property with the same name is seen in the @implementation
@@ -1126,14 +1128,10 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
// double bar = [foo bar];
// }
//
- if (GetterMethod) {
- CD->addDecl(Context, GetterMethod);
+ if (GetterMethod)
AddInstanceMethodToGlobalPool(GetterMethod);
- }
- if (SetterMethod) {
- CD->addDecl(Context, SetterMethod);
+ if (SetterMethod)
AddInstanceMethodToGlobalPool(SetterMethod);
- }
}
// Note: For class/category implemenations, allMethods/allProperties is
diff --git a/test/Sema/typedef-redef.c b/test/Sema/typedef-redef.c
index 76b8a3cdde..d6962f1cd1 100644
--- a/test/Sema/typedef-redef.c
+++ b/test/Sema/typedef-redef.c
@@ -7,7 +7,7 @@ typedef __SIZE_TYPE__ size_t;
typedef const int x; // expected-note {{previous definition is here}}
-extern x a;
+extern x a; // expected-note {{previous definition is here}}
typedef int x; // expected-error {{typedef redefinition with different types}}
-extern x a;
+extern x a; // expected-error{{redefinition of 'a' with a different type}}