diff options
-rw-r--r-- | include/clang/AST/Decl.h | 18 | ||||
-rw-r--r-- | include/clang/AST/DeclBase.h | 58 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticKinds.def | 2 | ||||
-rw-r--r-- | lib/AST/DeclBase.cpp | 13 | ||||
-rw-r--r-- | lib/AST/DeclSerialization.cpp | 7 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 10 | ||||
-rw-r--r-- | test/Sema/typedef-redef.c | 4 |
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}} |