diff options
43 files changed, 1235 insertions, 549 deletions
diff --git a/Driver/PrintParserCallbacks.cpp b/Driver/PrintParserCallbacks.cpp index f3ddb23a5f..8ec45f2703 100644 --- a/Driver/PrintParserCallbacks.cpp +++ b/Driver/PrintParserCallbacks.cpp @@ -185,13 +185,14 @@ namespace { /// Act on @defs() element found when parsing a structure. ClassName is the /// name of the referenced class. - virtual void ActOnDefs(Scope *S, SourceLocation DeclStart, + virtual void ActOnDefs(Scope *S, DeclTy *TagD, SourceLocation DeclStart, IdentifierInfo *ClassName, llvm::SmallVectorImpl<DeclTy*> &Decls) { llvm::cout << __FUNCTION__ << "\n"; } - virtual DeclTy *ActOnField(Scope *S, SourceLocation DeclStart, + virtual DeclTy *ActOnField(Scope *S, DeclTy *TagD, + SourceLocation DeclStart, Declarator &D, ExprTy *BitfieldWidth) { llvm::cout << __FUNCTION__ << "\n"; return 0; diff --git a/Driver/RewriteObjC.cpp b/Driver/RewriteObjC.cpp index 1b7ce5bece..290a668563 100644 --- a/Driver/RewriteObjC.cpp +++ b/Driver/RewriteObjC.cpp @@ -2169,14 +2169,18 @@ QualType RewriteObjC::getSuperStructType() { FieldTypes[0] = Context->getObjCIdType(); // struct objc_class *super; FieldTypes[1] = Context->getObjCClassType(); + // Create fields - FieldDecl *FieldDecls[2]; - - for (unsigned i = 0; i < 2; ++i) - FieldDecls[i] = FieldDecl::Create(*Context, SourceLocation(), 0, - FieldTypes[i]); + for (unsigned i = 0; i < 2; ++i) { + SuperStructDecl->addDecl(*Context, + FieldDecl::Create(*Context, SuperStructDecl, + SourceLocation(), 0, + FieldTypes[i], /*BitWidth=*/0, + /*Mutable=*/false, 0), + true); + } - SuperStructDecl->defineBody(*Context, FieldDecls, 4); + SuperStructDecl->completeDefinition(*Context); } return Context->getTagDeclType(SuperStructDecl); } @@ -2196,14 +2200,20 @@ QualType RewriteObjC::getConstantStringStructType() { FieldTypes[2] = Context->getPointerType(Context->CharTy); // long length; FieldTypes[3] = Context->LongTy; + // Create fields - FieldDecl *FieldDecls[4]; - - for (unsigned i = 0; i < 4; ++i) - FieldDecls[i] = FieldDecl::Create(*Context, SourceLocation(), 0, - FieldTypes[i]); - - ConstantStringDecl->defineBody(*Context, FieldDecls, 4); + for (unsigned i = 0; i < 4; ++i) { + ConstantStringDecl->addDecl(*Context, + FieldDecl::Create(*Context, + ConstantStringDecl, + SourceLocation(), 0, + FieldTypes[i], + /*BitWidth=*/0, + /*Mutable=*/true, 0), + true); + } + + ConstantStringDecl->completeDefinition(*Context); } return Context->getTagDeclType(ConstantStringDecl); } @@ -3788,8 +3798,9 @@ Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp) { ParenExpr *PE = new ParenExpr(SourceLocation(), SourceLocation(), BlkCast); //PE->dump(); - FieldDecl *FD = FieldDecl::Create(*Context, SourceLocation(), - &Context->Idents.get("FuncPtr"), Context->VoidPtrTy); + FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(), + &Context->Idents.get("FuncPtr"), Context->VoidPtrTy, + /*BitWidth=*/0, /*Mutable=*/true, 0); MemberExpr *ME = new MemberExpr(PE, true, FD, SourceLocation(), FD->getType()); CastExpr *FunkCast = new CStyleCastExpr(PtrToFuncCastType, ME, PtrToFuncCastType, SourceLocation(), SourceLocation()); diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 2a8b1c8a5b..45bb2c3637 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -513,10 +513,12 @@ private: void InitBuiltinTypes(); void InitBuiltinType(QualType &R, BuiltinType::Kind K); - /// setRecordDefinition - Used by RecordDecl::defineBody to inform ASTContext - /// about which RecordDecl serves as the definition of a particular - /// struct/union/class. This will eventually be used by enums as well. + /// setTagDefinition - Used by RecordDecl::completeDefinition and + /// EnumDecl::completeDefinition to inform + /// about which RecordDecl/EnumDecl serves as the definition of a particular + /// struct/union/class/enum. void setTagDefinition(TagDecl* R); + friend class EnumDecl; friend class RecordDecl; // Return the ObjC type encoding for a given type. diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 8fbb3f00e9..3b0eb551bb 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -115,12 +115,6 @@ class ScopedDecl : public NamedDecl { /// such as "int X, Y, *Z;" this indicates Decl for the next declarator. ScopedDecl *NextDeclarator; - /// When this decl is in scope while parsing, the Next field contains a - /// pointer to the shadowed decl of the same name. When the scope is popped, - /// Decls are relinked onto a containing decl object. - /// - ScopedDecl *Next; - /// 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. @@ -150,7 +144,7 @@ class ScopedDecl : public NamedDecl { protected: ScopedDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N, ScopedDecl *PrevDecl) - : NamedDecl(DK, L, N), NextDeclarator(PrevDecl), Next(0), + : NamedDecl(DK, L, N), NextDeclarator(PrevDecl), DeclCtx(reinterpret_cast<uintptr_t>(DC)) {} virtual ~ScopedDecl(); @@ -188,9 +182,6 @@ public: void setLexicalDeclContext(DeclContext *DC); - ScopedDecl *getNext() const { return Next; } - void setNext(ScopedDecl *N) { Next = N; } - /// getNextDeclarator - If this decl was part of a multi-declarator /// declaration, such as "int X, Y, *Z;" this returns the decl for the next /// declarator. Otherwise it returns null. @@ -680,22 +671,31 @@ protected: /// FieldDecl - An instance of this class is created by Sema::ActOnField to /// represent a member of a struct/union/class. -class FieldDecl : public NamedDecl { +class FieldDecl : public ScopedDecl { + bool Mutable : 1; QualType DeclType; Expr *BitWidth; protected: - FieldDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, QualType T, - Expr *BW = NULL) - : NamedDecl(DK, L, Id), DeclType(T), BitWidth(BW) {} - FieldDecl(SourceLocation L, IdentifierInfo *Id, QualType T, Expr *BW) - : NamedDecl(Field, L, Id), DeclType(T), BitWidth(BW) {} + FieldDecl(Kind DK, DeclContext *DC, SourceLocation L, + IdentifierInfo *Id, QualType T, Expr *BW, bool Mutable, + ScopedDecl *PrevDecl) + : ScopedDecl(DK, DC, L, Id, PrevDecl), Mutable(Mutable), DeclType(T), + BitWidth(BW) + { } + public: - static FieldDecl *Create(ASTContext &C, SourceLocation L, IdentifierInfo *Id, - QualType T, Expr *BW = NULL); + static FieldDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, + IdentifierInfo *Id, QualType T, Expr *BW, + bool Mutable, ScopedDecl *PrevDecl); QualType getType() const { return DeclType; } - + + /// isMutable - Determines whether this field is mutable (C++ only). + bool isMutable() const { return Mutable; } + + /// isBitfield - Determines whether this field is a bitfield. bool isBitField() const { return BitWidth != NULL; } + Expr *getBitWidth() const { return BitWidth; } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { @@ -888,9 +888,6 @@ protected: /// EnumDecl - Represents an enum. As an extension, we allow forward-declared /// enums. class EnumDecl : public TagDecl, public DeclContext { - // EnumDecl's DeclChain points to a linked list of EnumConstantDecl's which - // are linked together through their getNextDeclarator pointers. - /// IntegerType - This represent the integer type that the enum corresponds /// to for code generation purposes. Note that the enumerator constants may /// have a different type than this does. @@ -908,30 +905,46 @@ public: virtual void Destroy(ASTContext& C); - /// defineElements - When created, EnumDecl correspond to a forward declared - /// enum. This method is used to mark the decl as being defined, with the - /// specified list of enums. - void defineElements(EnumConstantDecl *ListHead, QualType NewType) { - assert(!isDefinition() && "Cannot redefine enums!"); - setDeclChain(ListHead); - setDefinition(true); - - IntegerType = NewType; - } + /// completeDefinition - When created, the EnumDecl corresponds to a + /// forward-declared enum. This method is used to mark the + /// declaration as being defined; it's enumerators have already been + /// added (via DeclContext::addDecl). NewType is the new underlying + /// type of the enumeration type. + void completeDefinition(ASTContext &C, QualType NewType); + // enumerator_iterator - Iterates through the enumerators of this + // enumeration. + struct enumerator_iterator : public DeclContext::decl_iterator { + typedef EnumConstantDecl* value_type; + typedef EnumConstantDecl* reference; + typedef EnumConstantDecl* pointer; + + enumerator_iterator() : DeclContext::decl_iterator() { } + + explicit enumerator_iterator(DeclContext::decl_iterator Pos) + : DeclContext::decl_iterator(Pos) { } + + reference operator*() const { + return cast<EnumConstantDecl>(DeclContext::decl_iterator::operator*()); + } + + pointer operator->() const { + return cast<EnumConstantDecl>(DeclContext::decl_iterator::operator*()); + } + }; + + enumerator_iterator enumerator_begin() const { + return enumerator_iterator(this->decls_begin()); + } + + enumerator_iterator enumerator_end() const { + return enumerator_iterator(this->decls_end()); + } + /// getIntegerType - Return the integer type this enum decl corresponds to. /// This returns a null qualtype for an enum forward definition. QualType getIntegerType() const { return IntegerType; } - - /// getEnumConstantList - Return the first EnumConstantDecl in the enum. - /// - EnumConstantDecl *getEnumConstantList() { - return cast_or_null<EnumConstantDecl>(getDeclChain()); - } - const EnumConstantDecl *getEnumConstantList() const { - return cast_or_null<const EnumConstantDecl>(getDeclChain()); - } - + static bool classof(const Decl *D) { return D->getKind() == Enum; } static bool classof(const EnumDecl *D) { return true; } static DeclContext *castToDeclContext(const EnumDecl *D) { @@ -957,16 +970,12 @@ protected: /// union Y { int A, B; }; // Has body with members A and B (FieldDecls). /// This decl will be marked invalid if *any* members are invalid. /// -class RecordDecl : public TagDecl { +class RecordDecl : public TagDecl, public DeclContext { /// HasFlexibleArrayMember - This is true if this struct ends with a flexible /// array member (e.g. int X[]) or if this union contains a struct that does. /// If so, this cannot be contained in arrays or other structs as a member. bool HasFlexibleArrayMember : 1; - /// Members/NumMembers - This is a new[]'d array of pointers to Decls. - FieldDecl **Members; // Null if not defined. - int NumMembers; // -1 if not defined. - protected: RecordDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id); @@ -993,42 +1002,74 @@ public: return cast_or_null<RecordDecl>(TagDecl::getDefinition(C)); } - /// getNumMembers - Return the number of members, or -1 if this is a forward - /// definition. - int getNumMembers() const { return NumMembers; } - const FieldDecl *getMember(unsigned i) const { return Members[i]; } - FieldDecl *getMember(unsigned i) { return Members[i]; } - // Iterator access to field members. - typedef FieldDecl **field_iterator; - typedef FieldDecl * const *field_const_iterator; + class field_iterator { + /// Current - Current position within the sequence of declarations + /// in this record. + DeclContext::decl_iterator Current; + + /// End - Last position in the sequence of declarations in this + /// record. + DeclContext::decl_iterator End; + + /// SkipToNextField - Advances the current position up to the next + /// FieldDecl. + void SkipToNextField() { + while (Current != End && !isa<FieldDecl>(*Current)) + ++Current; + } - field_iterator field_begin() { - assert(isDefinition() && "Not a definition!"); - return Members; - } - field_iterator field_end() { - assert(isDefinition() && "Not a definition!"); - return Members + getNumMembers(); - } + public: + typedef FieldDecl* value_type; + typedef FieldDecl* reference; + typedef FieldDecl* pointer; + typedef std::ptrdiff_t difference_type; + typedef std::forward_iterator_tag iterator_category; + + field_iterator() : Current(), End() { } + + field_iterator(DeclContext::decl_iterator C, DeclContext::decl_iterator E) + : Current(C), End(E) { + SkipToNextField(); + } + + reference operator*() const { return cast<FieldDecl>(*Current); } - field_const_iterator field_begin() const { - assert(isDefinition() && "Not a definition!"); - return Members; + pointer operator->() const { return cast<FieldDecl>(*Current); } + + field_iterator& operator++() { + ++Current; + SkipToNextField(); + return *this; + } + + field_iterator operator++(int) { + field_iterator tmp(*this); + ++(*this); + return tmp; + } + + friend bool operator==(const field_iterator& x, const field_iterator& y) { + return x.Current == y.Current; + } + + friend bool operator!=(const field_iterator& x, const field_iterator& y) { + return x.Current != y.Current; + } + }; + + typedef field_iterator field_const_iterator; + + field_iterator field_begin() const { + return field_iterator(decls_begin(), decls_end()); } - field_const_iterator field_end() const { - assert(isDefinition() && "Not a definition!"); - return Members + getNumMembers(); + field_iterator field_end() const { + return field_iterator(decls_end(), decls_end()); } - /// defineBody - When created, RecordDecl's correspond to a forward declared - /// record. This method is used to mark the decl as being defined, with the - /// specified contents. - void defineBody(ASTContext& C, FieldDecl **Members, unsigned numMembers); - - /// getMember - If the member doesn't exist, or there are no members, this - /// function will return 0; - FieldDecl *getMember(IdentifierInfo *name); + /// completeDefinition - Notes that the definition of this type is + /// now complete. + void completeDefinition(ASTContext& C); static bool classof(const Decl *D) { return D->getKind() >= RecordFirst && D->getKind() <= RecordLast; diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 55919da54e..badf6345ec 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -17,11 +17,14 @@ #include "clang/AST/Attr.h" #include "clang/AST/Type.h" #include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/PointerIntPair.h" +#include <vector> namespace clang { class DeclContext; class TranslationUnitDecl; class NamespaceDecl; +class NamedDecl; class ScopedDecl; class FunctionDecl; class CXXRecordDecl; @@ -29,6 +32,7 @@ class EnumDecl; class ObjCMethodDecl; class ObjCInterfaceDecl; class BlockDecl; +class DeclarationName; /// Decl - This represents one declaration (or definition), e.g. a variable, /// typedef, function, struct, etc. @@ -44,10 +48,6 @@ public: // Decl TranslationUnit, // [DeclContext] // NamedDecl - Field, - CXXField, - ObjCIvar, - ObjCAtDefsField, OverloadedFunction, ObjCCategory, ObjCCategoryImpl, @@ -56,13 +56,16 @@ public: ObjCProtocol, ObjCProperty, // ScopedDecl + Field, + ObjCIvar, + ObjCAtDefsField, Namespace, // [DeclContext] // TypeDecl Typedef, // TagDecl Enum, // [DeclContext] - Record, - CXXRecord, // [DeclContext] + Record, // [DeclContext] + CXXRecord, TemplateTypeParm, // ValueDecl EnumConstant, @@ -87,9 +90,9 @@ public: // For each non-leaf class, we now define a mapping to the first/last member // of the class, to allow efficient classof. - NamedFirst = Field , NamedLast = NonTypeTemplateParm, + NamedFirst = OverloadedFunction , NamedLast = NonTypeTemplateParm, FieldFirst = Field , FieldLast = ObjCAtDefsField, - ScopedFirst = Namespace , ScopedLast = NonTypeTemplateParm, + ScopedFirst = Field , ScopedLast = NonTypeTemplateParm, TypeFirst = Typedef , TypeLast = TemplateTypeParm, TagFirst = Enum , TagLast = CXXRecord, RecordFirst = Record , RecordLast = CXXRecord, @@ -183,10 +186,10 @@ public: case ParmVar: case EnumConstant: case NonTypeTemplateParm: + case Field: case ObjCInterface: case ObjCCompatibleAlias: case OverloadedFunction: - case CXXField: case CXXMethod: case CXXConversion: case CXXClassVar: @@ -247,7 +250,7 @@ protected: /// TranslationUnitDecl /// NamespaceDecl /// FunctionDecl -/// CXXRecordDecl +/// RecordDecl/CXXRecordDecl /// EnumDecl /// ObjCMethodDecl /// ObjCInterfaceDecl @@ -257,9 +260,26 @@ class DeclContext { /// DeclKind - This indicates which class this is. Decl::Kind DeclKind : 8; - /// DeclChain - Linked list of declarations that are defined inside this - /// declaration context. - ScopedDecl *DeclChain; + /// LookupPtrKind - Describes what kind of pointer LookupPtr + /// actually is. + enum LookupPtrKind { + /// LookupIsMap - Indicates that LookupPtr is actually a + /// DenseMap<DeclarationName, TwoNamedDecls> pointer. + LookupIsMap = 7 + }; + + /// LookupPtr - Pointer to a data structure used to lookup + /// declarations within this context. If the context contains fewer + /// than seven declarations, the number of declarations is provided + /// in the 3 lowest-order bits and the upper bits are treated as a + /// pointer to an array of NamedDecl pointers. If the context + /// contains seven or more declarations, the upper bits are treated + /// as a pointer to a DenseMap<DeclarationName, TwoNamedDecls>. + llvm::PointerIntPair<void*, 3> LookupPtr; + + /// Decls - Contains all of the declarations that are defined inside + /// this declaration context. + std::vector<ScopedDecl*> Decls; // Used in the CastTo template to get the DeclKind // from a Decl or a DeclContext. DeclContext doesn't have a getKind() method @@ -281,6 +301,8 @@ class DeclContext { return static_cast<NamespaceDecl*>(const_cast<From*>(D)); case Decl::Enum: return static_cast<EnumDecl*>(const_cast<From*>(D)); + case Decl::Record: + return static_cast<RecordDecl*>(const_cast<From*>(D)); case Decl::CXXRecord: return static_cast<CXXRecordDecl*>(const_cast<From*>(D)); case Decl::ObjCMethod: @@ -296,10 +318,19 @@ class DeclContext { } } + /// isLookupMap - Determine if the lookup structure is a + /// DenseMap. Othewise, it is an array. + bool isLookupMap() const { return LookupPtr.getInt() == LookupIsMap; } + protected: - DeclContext(Decl::Kind K) : DeclKind(K), DeclChain(0) {} + DeclContext(Decl::Kind K) : DeclKind(K), LookupPtr() { + } + + void DestroyDecls(ASTContext &C); public: + ~DeclContext(); + /// getParent - Returns the containing DeclContext if this is a ScopedDecl, /// else returns NULL. const DeclContext *getParent() const; @@ -309,12 +340,12 @@ public: } /// getLexicalParent - Returns the containing lexical DeclContext. May be - /// different from getParent, e.g.:
- ///
- /// namespace A {
- /// struct S;
- /// }
- /// struct A::S {}; // getParent() == namespace 'A'
+ /// different from getParent, e.g.: + /// + /// namespace A { + /// struct S; + /// } + /// struct A::S {}; // getParent() == namespace 'A' /// // getLexicalParent() == translation unit /// const DeclContext *getLexicalParent() const; @@ -326,11 +357,12 @@ public: bool isFunctionOrMethod() const { switch (DeclKind) { case Decl::Block: - case Decl::Function: - case Decl::CXXMethod: case Decl::ObjCMethod: return true; + default: + if (DeclKind >= Decl::FunctionFirst && DeclKind <= Decl::FunctionLast) + return true; return false; } } @@ -343,6 +375,10 @@ public: return DeclKind == Decl::CXXRecord; } + bool isNamespace() const { + return DeclKind == Decl::Namespace; + } + bool Encloses(DeclContext *DC) const { for (; DC; DC = DC->getParent()) if (DC == this) @@ -350,15 +386,105 @@ public: return false; } - const ScopedDecl *getDeclChain() const { return DeclChain; } - ScopedDecl *getDeclChain() { return DeclChain; } - void setDeclChain(ScopedDecl *D) { DeclChain = D; } + /// getPrimaryContext - There may be many different + /// declarations of the same entity (including forward declarations + /// of classes, multiple definitions of namespaces, etc.), each with + /// a different set of declarations. This routine returns the + /// "primary" DeclContext structure, which will contain the + /// information needed to perform name lookup into this context. + DeclContext *getPrimaryContext(ASTContext &Context); + + /// getNextContext - If this is a DeclContext that may have other + /// DeclContexts that are semantically connected but syntactically + /// different, such as C++ namespaces, this routine retrieves the + /// next DeclContext in the link. Iteration through the chain of + /// DeclContexts should begin at the primary DeclContext and + /// continue until this function returns NULL. For example, given: + /// @code + /// namespace N { + /// int x; + /// } + /// namespace N { + /// int y; + /// } + /// @endcode + /// The first occurrence of namespace N will be the primary + /// DeclContext. Its getNextContext will return the second + /// occurrence of namespace N. + DeclContext *getNextContext(); + + /// decl_iterator - Iterates through the declarations stored + /// within this context. + typedef std::vector<ScopedDecl*>::const_iterator decl_iterator; + + /// reverse_decl_iterator - Iterates through the declarations stored + /// within this context in reverse order. + typedef std::vector<ScopedDecl*>::const_reverse_iterator + reverse_decl_iterator; + + /// 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(); } + + /// decls_rbegin/decls_rend - Iterate over the declarations stored + /// in this context in reverse order. + reverse_decl_iterator decls_rbegin() const { return Decls.rbegin(); } + reverse_decl_iterator decls_rend() const { return Decls.rend(); } + + /// addDecl - Add the declaration D to this scope. Note that + /// declarations are added at the beginning of the declaration + /// chain, so reverseDeclChain() should be called after all + /// declarations have been added. If AllowLookup, also adds this + /// declaration into data structure for name lookup. + void addDecl(ASTContext &Context, ScopedDecl *D, bool AllowLookup = true); + + /// reverseDeclChain - Reverse the chain of declarations stored in + /// this scope. Typically called once after all declarations have + /// been added and the scope is closed. + void reverseDeclChain(); + + /// lookup_iterator - An iterator that provides access to the results + /// of looking up a name within this context. + typedef NamedDecl **lookup_iterator; + + /// lookup_const_iterator - An iterator that provides non-mutable + /// access to the results of lookup up a name within this context. + typedef NamedDecl * const * lookup_const_iterator; + + typedef std::pair<lookup_iterator, lookup_iterator> lookup_result; + typedef std::pair<lookup_const_iterator, lookup_const_iterator> + lookup_const_result; + + /// lookup - Find the declarations (if any) with the given Name in + /// this context. Returns a range of iterators that contains all of + /// the declarations with this name (which may be 0, 1, or 2 + /// declarations). If two declarations are returned, the declaration + /// in the "ordinary" identifier namespace will precede the + /// declaration in the "tag" identifier namespace (e.g., values + /// before types). Note that this routine will not look into parent + /// contexts. + lookup_result lookup(ASTContext &Context, DeclarationName Name); + lookup_const_result |