[cfe-commits] r60878 - in /cfe/trunk: Driver/ include/clang/AST/ include/clang/Parse/ lib/AST/ lib/Analysis/ lib/CodeGen/ lib/Parse/ lib/Sema/ test/SemaCXX/
Douglas Gregor
dgregor at apple.com
Thu Dec 11 08:49:31 PST 2008
Author: dgregor
Date: Thu Dec 11 10:49:14 2008
New Revision: 60878
URL: http://llvm.org/viewvc/llvm-project?rev=60878&view=rev
Log:
Unifies the name-lookup mechanisms used in various parts of the AST
and separates lexical name lookup from qualified name lookup. In
particular:
* Make DeclContext the central data structure for storing and
looking up declarations within existing declarations, e.g., members
of structs/unions/classes, enumerators in C++0x enums, members of
C++ namespaces, and (later) members of Objective-C
interfaces/implementations. DeclContext uses a lazily-constructed
data structure optimized for fast lookup (array for small contexts,
hash table for larger contexts).
* Implement C++ qualified name lookup in terms of lookup into
DeclContext.
* Implement C++ unqualified name lookup in terms of
qualified+unqualified name lookup (since unqualified lookup is not
purely lexical in C++!)
* Limit the use of the chains of declarations stored in
IdentifierInfo to those names declared lexically.
* Eliminate CXXFieldDecl, collapsing its behavior into
FieldDecl. (FieldDecl is now a ScopedDecl).
* Make RecordDecl into a DeclContext and eliminates its
Members/NumMembers fields (since one can just iterate through the
DeclContext to get the fields).
Added:
cfe/trunk/test/SemaCXX/qualified-id-lookup.cpp
Modified:
cfe/trunk/Driver/PrintParserCallbacks.cpp
cfe/trunk/Driver/RewriteObjC.cpp
cfe/trunk/include/clang/AST/ASTContext.h
cfe/trunk/include/clang/AST/Decl.h
cfe/trunk/include/clang/AST/DeclBase.h
cfe/trunk/include/clang/AST/DeclCXX.h
cfe/trunk/include/clang/AST/DeclObjC.h
cfe/trunk/include/clang/AST/DeclarationName.h
cfe/trunk/include/clang/Parse/Action.h
cfe/trunk/include/clang/Parse/Scope.h
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/AST/Decl.cpp
cfe/trunk/lib/AST/DeclBase.cpp
cfe/trunk/lib/AST/DeclCXX.cpp
cfe/trunk/lib/AST/DeclObjC.cpp
cfe/trunk/lib/AST/DeclSerialization.cpp
cfe/trunk/lib/AST/DeclarationName.cpp
cfe/trunk/lib/AST/Expr.cpp
cfe/trunk/lib/AST/ExprConstant.cpp
cfe/trunk/lib/Analysis/RegionStore.cpp
cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
cfe/trunk/lib/CodeGen/CGExprAgg.cpp
cfe/trunk/lib/CodeGen/CGExprConstant.cpp
cfe/trunk/lib/CodeGen/CGObjCMac.cpp
cfe/trunk/lib/CodeGen/CodeGenModule.cpp
cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Sema/CXXFieldCollector.h
cfe/trunk/lib/Sema/IdentifierResolver.cpp
cfe/trunk/lib/Sema/IdentifierResolver.h
cfe/trunk/lib/Sema/Sema.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclAttr.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaDeclObjC.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/lib/Sema/SemaInit.cpp
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/test/SemaCXX/namespace.cpp
Modified: cfe/trunk/Driver/PrintParserCallbacks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/PrintParserCallbacks.cpp?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/Driver/PrintParserCallbacks.cpp (original)
+++ cfe/trunk/Driver/PrintParserCallbacks.cpp Thu Dec 11 10:49:14 2008
@@ -185,13 +185,14 @@
/// 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;
Modified: cfe/trunk/Driver/RewriteObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/RewriteObjC.cpp?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/Driver/RewriteObjC.cpp (original)
+++ cfe/trunk/Driver/RewriteObjC.cpp Thu Dec 11 10:49:14 2008
@@ -2169,14 +2169,18 @@
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 @@
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 @@
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());
Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Thu Dec 11 10:49:14 2008
@@ -513,10 +513,12 @@
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.
Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Thu Dec 11 10:49:14 2008
@@ -115,12 +115,6 @@
/// 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 @@
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 @@
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 @@
/// 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 @@
/// 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 @@
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 @@
/// 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 @@
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); }
+
+ pointer operator->() const { return cast<FieldDecl>(*Current); }
- field_const_iterator field_begin() const {
- assert(isDefinition() && "Not a definition!");
- return Members;
+ 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;
Modified: cfe/trunk/include/clang/AST/DeclBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Thu Dec 11 10:49:14 2008
@@ -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 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 @@
// Decl
TranslationUnit, // [DeclContext]
// NamedDecl
- Field,
- CXXField,
- ObjCIvar,
- ObjCAtDefsField,
OverloadedFunction,
ObjCCategory,
ObjCCategoryImpl,
@@ -56,13 +56,16 @@
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 @@
// 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 @@
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 @@
/// TranslationUnitDecl
/// NamespaceDecl
/// FunctionDecl
-/// CXXRecordDecl
+/// RecordDecl/CXXRecordDecl
/// EnumDecl
/// ObjCMethodDecl
/// ObjCInterfaceDecl
@@ -257,9 +260,26 @@
/// 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 @@
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 @@
}
}
+ /// 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 @@
}
/// 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 @@
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 @@
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 @@
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 lookup(ASTContext &Context, DeclarationName Name) const;
+
+ /// insert - Insert the declaration D into this context. Up to two
+ /// declarations with the same name can be inserted into a single
+ /// declaration context, one in the "tag" namespace (e.g., for
+ /// classes and enums) and one in the "ordinary" namespaces (e.g.,
+ /// for variables, functions, and other values). Note that, if there
+ /// is already a declaration with the same name and identifier
+ /// namespace, D will replace it. It is up to the caller to ensure
+ /// that this replacement is semantically correct, e.g., that
+ /// declarations are only replaced by later declarations of the same
+ /// entity and not a declaration of some other kind of entity.
+ void insert(ASTContext &Context, NamedDecl *D);
static bool classof(const Decl *D) {
switch (D->getKind()) {
case Decl::TranslationUnit:
case Decl::Namespace:
case Decl::Enum:
+ case Decl::Record:
case Decl::CXXRecord:
case Decl::ObjCMethod:
case Decl::ObjCInterface:
@@ -375,6 +501,7 @@
static bool classof(const TranslationUnitDecl *D) { return true; }
static bool classof(const NamespaceDecl *D) { return true; }
static bool classof(const FunctionDecl *D) { return true; }
+ static bool classof(const RecordDecl *D) { return true; }
static bool classof(const CXXRecordDecl *D) { return true; }
static bool classof(const EnumDecl *D) { return true; }
static bool classof(const ObjCMethodDecl *D) { return true; }
@@ -382,6 +509,8 @@
static bool classof(const BlockDecl *D) { return true; }
private:
+ void insertImpl(NamedDecl *D);
+
void EmitOutRec(llvm::Serializer& S) const;
void ReadOutRec(llvm::Deserializer& D, ASTContext& C);
@@ -430,6 +559,20 @@
}
};
+template<class FromTy>
+struct cast_convert_val< const ::clang::DeclContext, FromTy, FromTy> {
+ static const ::clang::DeclContext &doit(const FromTy &Val) {
+ return *FromTy::castToDeclContext(&Val);
+ }
+};
+
+template<class FromTy>
+struct cast_convert_val< const ::clang::DeclContext, FromTy*, FromTy*> {
+ static const ::clang::DeclContext *doit(const FromTy *Val) {
+ return FromTy::castToDeclContext(Val);
+ }
+};
+
/// Implement cast_convert_val for DeclContext -> Decl conversions.
template<class ToTy>
struct cast_convert_val<ToTy,
Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Thu Dec 11 10:49:14 2008
@@ -116,8 +116,6 @@
/// addOverload - Add an overloaded function FD to this set of
/// overloaded functions.
void addOverload(FunctionDecl *FD) {
- assert((!getNumFunctions() || (FD->getDeclContext() == getDeclContext())) &&
- "Overloaded functions must all be in the same context");
assert((FD->getDeclName() == getDeclName() ||
isa<CXXConversionDecl>(FD) || isa<CXXConstructorDecl>(FD)) &&
"Overloaded functions must have the same name");
@@ -173,29 +171,6 @@
friend class CXXRecordDecl;
};
-/// CXXFieldDecl - Represents an instance field of a C++ struct/union/class.
-class CXXFieldDecl : public FieldDecl {
- CXXRecordDecl *Parent;
- bool Mutable;
-
- CXXFieldDecl(CXXRecordDecl *RD, SourceLocation L, IdentifierInfo *Id,
- QualType T, bool Mut, Expr *BW = NULL)
- : FieldDecl(CXXField, L, Id, T, BW), Parent(RD), Mutable(Mut) {}
-public:
- static CXXFieldDecl *Create(ASTContext &C, CXXRecordDecl *RD,SourceLocation L,
- IdentifierInfo *Id, QualType T, bool Mut,
- Expr *BW = NULL);
-
- void setAccess(AccessSpecifier AS) { Access = AS; }
- AccessSpecifier getAccess() const { return AccessSpecifier(Access); }
- CXXRecordDecl *getParent() const { return Parent; }
- bool isMutable() const { return Mutable; }
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Decl *D) { return D->getKind() == CXXField; }
- static bool classof(const CXXFieldDecl *D) { return true; }
-};
-
/// CXXBaseSpecifier - A base class of a C++ class.
///
/// Each CXXBaseSpecifier represents a single, direct base class (or
@@ -277,11 +252,9 @@
};
/// CXXRecordDecl - Represents a C++ struct/union/class.
-/// CXXRecordDecl differs from RecordDecl in several ways. First, it
-/// is a DeclContext, because it can contain other
-/// declarations. Second, it provides additional C++ fields, including
-/// storage for base classes and constructors.
-class CXXRecordDecl : public RecordDecl, public DeclContext {
+/// FIXME: This class will disappear once we've properly taught RecordDecl
+/// to deal with C++-specific things.
+class CXXRecordDecl : public RecordDecl {
/// UserDeclaredConstructor - True when this class has a
/// user-declared constructor.
bool UserDeclaredConstructor : 1;
@@ -348,19 +321,6 @@
base_class_iterator bases_end() { return Bases + NumBases; }
base_class_const_iterator bases_end() const { return Bases + NumBases; }
- const CXXFieldDecl *getMember(unsigned i) const {
- return cast<const CXXFieldDecl>(RecordDecl::getMember(i));
- }
- CXXFieldDecl *getMember(unsigned i) {
- return cast<CXXFieldDecl>(RecordDecl::getMember(i));
- }
-
- /// getMember - If the member doesn't exist, or there are no members, this
- /// function will return 0;
- CXXFieldDecl *getMember(IdentifierInfo *name) {
- return cast_or_null<CXXFieldDecl>(RecordDecl::getMember(name));
- }
-
/// getConstructors - Retrieve the overload set containing all of
/// the constructors of this class.
OverloadedFunctionDecl *getConstructors() { return &Constructors; }
@@ -537,7 +497,7 @@
class CXXBaseOrMemberInitializer {
/// BaseOrMember - This points to the entity being initialized,
/// which is either a base class (a Type) or a non-static data
- /// member (a CXXFieldDecl). When the low bit is 1, it's a base
+ /// member. When the low bit is 1, it's a base
/// class; when the low bit is 0, it's a member.
uintptr_t BaseOrMember;
@@ -552,7 +512,7 @@
/// CXXBaseOrMemberInitializer - Creates a new member initializer.
explicit
- CXXBaseOrMemberInitializer(CXXFieldDecl *Member, Expr **Args, unsigned NumArgs);
+ CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs);
/// ~CXXBaseOrMemberInitializer - Destroy the base or member initializer.
~CXXBaseOrMemberInitializer();
@@ -598,9 +558,9 @@
/// getMember - If this is a member initializer, returns the
/// declaration of the non-static data member being
/// initialized. Otherwise, returns NULL.
- CXXFieldDecl *getMember() {
+ FieldDecl *getMember() {
if (isMemberInitializer())
- return reinterpret_cast<CXXFieldDecl *>(BaseOrMember);
+ return reinterpret_cast<FieldDecl *>(BaseOrMember);
else
return 0;
}
@@ -917,14 +877,14 @@
if (ScopedDecl *SD = dyn_cast<ScopedDecl>(MD)) {
return cast<CXXRecordDecl>(SD->getDeclContext());
}
- return cast<CXXFieldDecl>(MD)->getParent();
+ return cast<CXXRecordDecl>(cast<FieldDecl>(MD)->getDeclContext());
}
static bool isMember(Decl *D) {
if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
return isa<CXXRecordDecl>(SD->getDeclContext());
}
- return isa<CXXFieldDecl>(D);
+ return isa<FieldDecl>(D);
}
};
Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Thu Dec 11 10:49:14 2008
@@ -506,7 +506,8 @@
private:
ObjCIvarDecl(SourceLocation L, IdentifierInfo *Id, QualType T,
AccessControl ac, Expr *BW)
- : FieldDecl(ObjCIvar, L, Id, T, BW), DeclAccess(ac) {}
+ : FieldDecl(ObjCIvar, 0, L, Id, T, BW, /*Mutable=*/false, 0),
+ DeclAccess(ac) {}
public:
static ObjCIvarDecl *Create(ASTContext &C, SourceLocation L,
@@ -534,12 +535,13 @@
/// @defs(...).
class ObjCAtDefsFieldDecl : public FieldDecl {
private:
- ObjCAtDefsFieldDecl(SourceLocation L, IdentifierInfo *Id,
+ ObjCAtDefsFieldDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
QualType T, Expr *BW)
- : FieldDecl(ObjCAtDefsField, L, Id, T, BW) {}
+ : FieldDecl(ObjCAtDefsField, DC, L, Id, T, BW, /*Mutable=*/false, 0) {}
public:
- static ObjCAtDefsFieldDecl *Create(ASTContext &C, SourceLocation L,
+ static ObjCAtDefsFieldDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
IdentifierInfo *Id, QualType T,
Expr *BW);
Modified: cfe/trunk/include/clang/AST/DeclarationName.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclarationName.h?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclarationName.h (original)
+++ cfe/trunk/include/clang/AST/DeclarationName.h Thu Dec 11 10:49:14 2008
@@ -198,6 +198,10 @@
/// name as an opaque integer.
uintptr_t getAsOpaqueInteger() const { return Ptr; }
+ /// getAsOpaquePtr - Get the representation of this declaration name as
+ /// an opaque pointer.
+ void *getAsOpaquePtr() const { return reinterpret_cast<void*>(Ptr); }
+
static DeclarationName getFromOpaqueInteger(uintptr_t P) {
DeclarationName N;
N.Ptr = P;
Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Thu Dec 11 10:49:14 2008
@@ -265,10 +265,10 @@
/// 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) {}
- virtual DeclTy *ActOnField(Scope *S, SourceLocation DeclStart,
+ virtual DeclTy *ActOnField(Scope *S, DeclTy *TagD, SourceLocation DeclStart,
Declarator &D, ExprTy *BitfieldWidth) {
return 0;
}
Modified: cfe/trunk/include/clang/Parse/Scope.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Scope.h?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Scope.h (original)
+++ cfe/trunk/include/clang/Parse/Scope.h Thu Dec 11 10:49:14 2008
@@ -112,6 +112,12 @@
typedef llvm::SmallPtrSet<Action::DeclTy*, 32> DeclSetTy;
DeclSetTy DeclsInScope;
+ /// Entity - The entity with which this scope is associated. For
+ /// example, the entity of a class scope is the class itself, the
+ /// entity of a function scope is a function, etc. This field is
+ /// maintained by the Action implementation.
+ void *Entity;
+
public:
Scope(Scope *Parent, unsigned ScopeFlags) {
Init(Parent, ScopeFlags);
@@ -178,12 +184,19 @@
DeclsInScope.insert(D);
}
+ void RemoveDecl(Action::DeclTy *D) {
+ DeclsInScope.erase(D);
+ }
+
/// isDeclScope - Return true if this is the scope that the specified decl is
/// declared in.
bool isDeclScope(Action::DeclTy *D) {
return DeclsInScope.count(D) != 0;
}
+ void* getEntity() const { return Entity; }
+ void setEntity(void *E) { Entity = E; }
+
/// isCXXClassScope - Return true if this scope is a C++ class scope.
bool isCXXClassScope() const {
return (getFlags() & Scope::CXXClassScope);
@@ -242,6 +255,7 @@
if (Flags & BlockScope) BlockParent = this;
if (Flags & TemplateParamScope) TemplateParamParent = this;
DeclsInScope.clear();
+ Entity = 0;
}
};
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Thu Dec 11 10:49:14 2008
@@ -539,7 +539,7 @@
ASTRecordLayout *NewEntry = new ASTRecordLayout();
Entry = NewEntry;
- NewEntry->InitializeLayout(D->getNumMembers());
+ NewEntry->InitializeLayout(std::distance(D->field_begin(), D->field_end()));
bool IsUnion = D->isUnion();
unsigned StructPacking = 0;
@@ -552,10 +552,11 @@
// Layout each field, for now, just sequentially, respecting alignment. In
// the future, this will need to be tweakable by targets.
- for (unsigned i = 0, e = D->getNumMembers(); i != e; ++i) {
- const FieldDecl *FD = D->getMember(i);
- NewEntry->LayoutField(FD, i, IsUnion, StructPacking, *this);
- }
+ unsigned FieldIdx = 0;
+ for (RecordDecl::field_iterator Field = D->field_begin(),
+ FieldEnd = D->field_end();
+ Field != FieldEnd; (void)++Field, ++FieldIdx)
+ NewEntry->LayoutField(*Field, FieldIdx, IsUnion, StructPacking, *this);
// Finally, round the size of the total struct up to the alignment of the
// struct itself.
@@ -996,12 +997,16 @@
return QualType(Decl->TypeForDecl, 0);
}
-/// setTagDefinition - 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 ASTContext::setTagDefinition(TagDecl* D) {
assert (D->isDefinition());
- cast<TagType>(D->TypeForDecl)->decl = D;
+ if (!D->TypeForDecl)
+ getTypeDeclType(D);
+ else
+ cast<TagType>(D->TypeForDecl)->decl = D;
}
/// getTypedefType - Return the unique reference to the type for the
@@ -1460,14 +1465,17 @@
FieldTypes[2] = getPointerType(CharTy.getQualifiedType(QualType::Const));
// long length;
FieldTypes[3] = LongTy;
- // Create fields
- FieldDecl *FieldDecls[4];
-
- for (unsigned i = 0; i < 4; ++i)
- FieldDecls[i] = FieldDecl::Create(*this, SourceLocation(), 0,
- FieldTypes[i]);
- CFConstantStringTypeDecl->defineBody(*this, FieldDecls, 4);
+ // Create fields
+ for (unsigned i = 0; i < 4; ++i) {
+ FieldDecl *Field = FieldDecl::Create(*this, CFConstantStringTypeDecl,
+ SourceLocation(), 0,
+ FieldTypes[i], /*BitWidth=*/0,
+ /*Mutable=*/false, /*PrevDecl=*/0);
+ CFConstantStringTypeDecl->addDecl(*this, Field, true);
+ }
+
+ CFConstantStringTypeDecl->completeDefinition(*this);
}
return getTagDeclType(CFConstantStringTypeDecl);
@@ -1476,6 +1484,10 @@
QualType ASTContext::getObjCFastEnumerationStateType()
{
if (!ObjCFastEnumerationStateTypeDecl) {
+ ObjCFastEnumerationStateTypeDecl =
+ RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
+ &Idents.get("__objcFastEnumerationState"));
+
QualType FieldTypes[] = {
UnsignedLongTy,
getPointerType(ObjCIdType),
@@ -1484,16 +1496,16 @@
llvm::APInt(32, 5), ArrayType::Normal, 0)
};
- FieldDecl *FieldDecls[4];
- for (size_t i = 0; i < 4; ++i)
- FieldDecls[i] = FieldDecl::Create(*this, SourceLocation(), 0,
- FieldTypes[i]);
-
- ObjCFastEnumerationStateTypeDecl =
- RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
- &Idents.get("__objcFastEnumerationState"));
+ for (size_t i = 0; i < 4; ++i) {
+ FieldDecl *Field = FieldDecl::Create(*this,
+ ObjCFastEnumerationStateTypeDecl,
+ SourceLocation(), 0,
+ FieldTypes[i], /*BitWidth=*/0,
+ /*Mutable=*/false, /*PrevDecl=*/0);
+ ObjCFastEnumerationStateTypeDecl->addDecl(*this, Field, true);
+ }
- ObjCFastEnumerationStateTypeDecl->defineBody(*this, FieldDecls, 4);
+ ObjCFastEnumerationStateTypeDecl->completeDefinition(*this);
}
return getTagDeclType(ObjCFastEnumerationStateTypeDecl);
@@ -1745,16 +1757,17 @@
}
if (ExpandStructures) {
S += '=';
- for (int i = 0; i < RDecl->getNumMembers(); i++) {
- FieldDecl *FD = RDecl->getMember(i);
+ for (RecordDecl::field_iterator Field = RDecl->field_begin(),
+ FieldEnd = RDecl->field_end();
+ Field != FieldEnd; ++Field) {
if (NameFields) {
S += '"';
- S += FD->getNameAsString();
+ S += Field->getNameAsString();
S += '"';
}
// Special case bit-fields.
- if (const Expr *E = FD->getBitWidth()) {
+ if (const Expr *E = Field->getBitWidth()) {
// FIXME: Fix constness.
ASTContext *Ctx = const_cast<ASTContext*>(this);
unsigned N = E->getIntegerConstantExprValue(*Ctx).getZExtValue();
@@ -1763,7 +1776,8 @@
S += 'b';
S += llvm::utostr(N);
} else {
- getObjCEncodingForTypeImpl(FD->getType(), S, false, true, NameFields);
+ getObjCEncodingForTypeImpl(Field->getType(), S, false, true,
+ NameFields);
}
}
}
Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Thu Dec 11 10:49:14 2008
@@ -81,10 +81,11 @@
return new (Mem) BlockDecl(DC, L);
}
-FieldDecl *FieldDecl::Create(ASTContext &C, SourceLocation L,
- IdentifierInfo *Id, QualType T, Expr *BW) {
+FieldDecl *FieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
+ IdentifierInfo *Id, QualType T, Expr *BW,
+ bool Mutable, ScopedDecl *PrevDecl) {
void *Mem = C.getAllocator().Allocate<FieldDecl>();
- return new (Mem) FieldDecl(L, Id, T, BW);
+ return new (Mem) FieldDecl(Decl::Field, DC, L, Id, T, BW, Mutable, PrevDecl);
}
@@ -118,10 +119,21 @@
}
void EnumDecl::Destroy(ASTContext& C) {
- if (getEnumConstantList()) getEnumConstantList()->Destroy(C);
+ DeclContext::DestroyDecls(C);
Decl::Destroy(C);
}
+void EnumDecl::completeDefinition(ASTContext &C, QualType NewType) {
+ assert(!isDefinition() && "Cannot redefine enums!");
+ setDefinition(true);
+
+ IntegerType = NewType;
+
+ // Let ASTContext know that this is the defining EnumDecl for this
+ // type.
+ C.setTagDefinition(this);
+}
+
FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C,
SourceLocation L,
StringLiteral *Str) {
@@ -248,12 +260,10 @@
RecordDecl::RecordDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id)
-: TagDecl(DK, TK, DC, L, Id, 0) {
+ : TagDecl(DK, TK, DC, L, Id, 0), DeclContext(DK) {
HasFlexibleArrayMember = false;
assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!");
- Members = 0;
- NumMembers = -1;
}
RecordDecl *RecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
@@ -267,46 +277,25 @@
}
RecordDecl::~RecordDecl() {
- delete[] Members;
}
void RecordDecl::Destroy(ASTContext& C) {
- if (isDefinition())
- for (field_iterator I=field_begin(), E=field_end(); I!=E; ++I)
- (*I)->Destroy(C);
-
+ DeclContext::DestroyDecls(C);
TagDecl::Destroy(C);
}
-/// 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 RecordDecl::defineBody(ASTContext& C, FieldDecl **members,
- unsigned numMembers) {
+/// completeDefinition - Notes that the definition of this type is now
+/// complete.
+void RecordDecl::completeDefinition(ASTContext& C) {
assert(!isDefinition() && "Cannot redefine record!");
+
setDefinition(true);
- NumMembers = numMembers;
- if (numMembers) {
- Members = new FieldDecl*[numMembers];
- memcpy(Members, members, numMembers*sizeof(Decl*));
- }
- // Let ASTContext know that this is the defining RecordDecl this type.
+ // Let ASTContext know that this is the defining RecordDecl for this
+ // type.
C.setTagDefinition(this);
}
-
-FieldDecl *RecordDecl::getMember(IdentifierInfo *II) {
- if (Members == 0 || NumMembers < 0)
- return 0;
-
- // Linear search. When C++ classes come along, will likely need to revisit.
- for (int i = 0; i != NumMembers; ++i)
- if (Members[i]->getIdentifier() == II)
- return Members[i];
- return 0;
-}
-
//===----------------------------------------------------------------------===//
// BlockDecl Implementation
//===----------------------------------------------------------------------===//
Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Thu Dec 11 10:49:14 2008
@@ -15,6 +15,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/Type.h"
#include "llvm/ADT/DenseMap.h"
using namespace clang;
@@ -34,7 +35,6 @@
static unsigned nOverFuncs = 0;
static unsigned nTypedef = 0;
static unsigned nFieldDecls = 0;
-static unsigned nCXXFieldDecls = 0;
static unsigned nInterfaceDecls = 0;
static unsigned nClassDecls = 0;
static unsigned nMethodDecls = 0;
@@ -95,7 +95,7 @@
void Decl::PrintStats() {
fprintf(stderr, "*** Decl Stats:\n");
fprintf(stderr, " %d decls total.\n",
- int(nFuncs+nVars+nParmVars+nFieldDecls+nSUC+nCXXFieldDecls+nCXXSUC+
+ int(nFuncs+nVars+nParmVars+nFieldDecls+nSUC+nCXXSUC+
nEnumDecls+nEnumConst+nTypedef+nInterfaceDecls+nClassDecls+
nMethodDecls+nProtocolDecls+nCategoryDecls+nIvarDecls+
nAtDefsFieldDecls+nNamespaces+nOverFuncs));
@@ -122,9 +122,6 @@
fprintf(stderr, " %d struct/union/class decls, %d each (%d bytes)\n",
nSUC, (int)sizeof(RecordDecl),
int(nSUC*sizeof(RecordDecl)));
- fprintf(stderr, " %d C++ field decls, %d each (%d bytes)\n",
- nCXXFieldDecls, (int)sizeof(CXXFieldDecl),
- int(nCXXFieldDecls*sizeof(CXXFieldDecl)));
fprintf(stderr, " %d C++ struct/union/class decls, %d each (%d bytes)\n",
nCXXSUC, (int)sizeof(CXXRecordDecl),
int(nCXXSUC*sizeof(CXXRecordDecl)));
@@ -183,7 +180,7 @@
int(nFuncs*sizeof(FunctionDecl)+
nVars*sizeof(VarDecl)+nParmVars*sizeof(ParmVarDecl)+
nFieldDecls*sizeof(FieldDecl)+nSUC*sizeof(RecordDecl)+
- nCXXFieldDecls*sizeof(CXXFieldDecl)+nCXXSUC*sizeof(CXXRecordDecl)+
+ nCXXSUC*sizeof(CXXRecordDecl)+
nEnumDecls*sizeof(EnumDecl)+nEnumConst*sizeof(EnumConstantDecl)+
nTypedef*sizeof(TypedefDecl)+
nInterfaceDecls*sizeof(ObjCInterfaceDecl)+
@@ -236,7 +233,6 @@
case ImplicitParam:
case TranslationUnit: break;
- case CXXField: nCXXFieldDecls++; break;
case CXXRecord: nCXXSUC++; break;
// FIXME: Statistics for C++ decls.
case TemplateTypeParm:
@@ -372,3 +368,269 @@
return SD->getLexicalDeclContext();
return getParent();
}
+
+/// TwoNamedDecls - Stores up to two NamedDecls. The first
+/// declaration, if any, is in the ordinary identifier namespace, and
+/// corresponds to values (functions, variables, etc.). The second
+/// declaration, if any, is in the tag identifier namespace, and
+/// corresponds to tag types (classes, enums).
+struct TwoNamedDecls {
+ NamedDecl* Decls[2];
+};
+
+// FIXME: We really want to use a DenseSet here to eliminate the
+// redundant storage of the declaration names, but (1) it doesn't give
+// us the ability to search based on DeclarationName, (2) we really
+// need something more like a DenseMultiSet, and (3) it's
+// implemented in terms of DenseMap anyway.
+typedef llvm::DenseMap<DeclarationName, TwoNamedDecls> StoredDeclsMap;
+
+DeclContext::~DeclContext() {
+ unsigned Size = LookupPtr.getInt();
+ if (Size == LookupIsMap) {
+ StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
+ delete Map;
+ } else {
+ NamedDecl **Array = static_cast<NamedDecl**>(LookupPtr.getPointer());
+ delete [] Array;
+ }
+}
+
+void DeclContext::DestroyDecls(ASTContext &C) {
+ for (decl_iterator D = Decls.begin(); D != Decls.end(); ++D) {
+ if ((*D)->getLexicalDeclContext() == this)
+ (*D)->Destroy(C);
+ }
+}
+
+DeclContext *DeclContext::getPrimaryContext(ASTContext &Context) {
+ switch (DeclKind) {
+ case Decl::Block:
+ case Decl::TranslationUnit:
+ // There is only one DeclContext for these entities.
+ return this;
+
+ case Decl::Namespace:
+ // The original namespace is our primary context.
+ return static_cast<NamespaceDecl*>(this)->getOriginalNamespace();
+
+ case Decl::Enum:
+ // The declaration associated with the enumeration type is our
+ // primary context.
+ return Context.getTypeDeclType(static_cast<EnumDecl*>(this))
+ ->getAsEnumType()->getDecl();
+
+ case Decl::Record:
+ case Decl::CXXRecord: {
+ // The declaration associated with the type is be our primary
+ // context.
+#if 0
+ // FIXME: This is what we expect to do. However, it doesn't work
+ // because ASTContext::setTagDefinition changes the result of
+ // Context.getTypeDeclType, meaning that our "primary" declaration
+ // of a RecordDecl/CXXRecordDecl will change, and we won't be able
+ // to find any values inserted into the earlier "primary"
+ // declaration. We need better tracking of redeclarations and
+ // definitions.
+ QualType Type = Context.getTypeDeclType(static_cast<RecordDecl*>(this));
+ return Type->getAsRecordType()->getDecl();
+#else
+ // FIXME: This hack will work for now, because the declaration we
+ // create when we're defining the record is the one we'll use as
+ // the definition later.
+ return this;
+#endif
+ }
+
+ case Decl::ObjCMethod:
+ return this;
+
+ case Decl::ObjCInterface:
+ // FIXME: Can Objective-C interfaces be forward-declared?
+ return this;
+
+ default:
+ assert(DeclKind >= Decl::FunctionFirst && DeclKind <= Decl::FunctionLast &&
+ "Unknown DeclContext kind");
+ return this;
+ }
+}
+
+DeclContext *DeclContext::getNextContext() {
+ switch (DeclKind) {
+ case Decl::Block:
+ case Decl::TranslationUnit:
+ case Decl::Enum:
+ case Decl::Record:
+ case Decl::CXXRecord:
+ case Decl::ObjCMethod:
+ case Decl::ObjCInterface:
+ // There is only one DeclContext for these entities.
+ return 0;
+
+ case Decl::Namespace:
+ // Return the next namespace
+ return static_cast<NamespaceDecl*>(this)->getNextNamespace();
+
+ default:
+ assert(DeclKind >= Decl::FunctionFirst && DeclKind <= Decl::FunctionLast &&
+ "Unknown DeclContext kind");
+ return 0;
+ }
+}
+
+void DeclContext::addDecl(ASTContext &Context, ScopedDecl *D, bool AllowLookup) {
+ Decls.push_back(D);
+ if (AllowLookup)
+ D->getDeclContext()->insert(Context, D);
+}
+
+DeclContext::lookup_result
+DeclContext::lookup(ASTContext &Context, DeclarationName Name) {
+ DeclContext *PrimaryContext = getPrimaryContext(Context);
+ if (PrimaryContext != this)
+ return PrimaryContext->lookup(Context, Name);
+
+ /// If there is no lookup data structure, build one now by talking
+ /// all of the linked DeclContexts (in declaration order!) and
+ /// inserting their values.
+ if (LookupPtr.getPointer() == 0) {
+ for (DeclContext *DCtx = this; DCtx; DCtx = DCtx->getNextContext())
+ for (decl_iterator D = DCtx->decls_begin(); D != DCtx->decls_end(); ++D)
+ insertImpl(*D);
+ }
+
+ lookup_result Result(0, 0);
+ if (isLookupMap()) {
+ StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
+ StoredDeclsMap::iterator Pos = Map->find(Name);
+ if (Pos != Map->end()) {
+ Result.first = Pos->second.Decls[0]? &Pos->second.Decls[0]
+ : &Pos->second.Decls[1];
+ Result.second = Pos->second.Decls[1]? &Pos->second.Decls[2]
+ : &Pos->second.Decls[1];
+ }
+ return Result;
+ }
+
+ // We have a small array. Look into it.
+ unsigned Size = LookupPtr.getInt();
+ NamedDecl **Array = static_cast<NamedDecl**>(LookupPtr.getPointer());
+ for (unsigned Idx = 0; Idx < Size; ++Idx)
+ if (Array[Idx]->getDeclName() == Name) {
+ Result.first = &Array[Idx];
+ Result.second = Result.first + 1;
+ if (Idx + 1 < Size && Array[Idx + 1]->getDeclName() == Name)
+ ++Result.second;
+ break;
+ }
+
+ return Result;
+}
+
+DeclContext::lookup_const_result
+DeclContext::lookup(ASTContext &Context, DeclarationName Name) const {
+ return const_cast<DeclContext*>(this)->lookup(Context, Name);
+}
+
+void DeclContext::insert(ASTContext &Context, NamedDecl *D) {
+ DeclContext *PrimaryContext = getPrimaryContext(Context);
+ if (PrimaryContext != this) {
+ PrimaryContext->insert(Context, D);
+ return;
+ }
+
+ // If we already have a lookup data structure, perform the insertion
+ // into it. Otherwise, be lazy and don't build that structure until
+ // someone asks for it.
+ if (LookupPtr.getPointer())
+ insertImpl(D);
+}
+
+void DeclContext::insertImpl(NamedDecl *D) {
+ if (!isLookupMap()) {
+ unsigned Size = LookupPtr.getInt();
+
+ // The lookup data is stored as an array. Search through the array
+ // to find the insertion location.
+ NamedDecl **Array;
+ if (Size == 0) {
+ Array = new NamedDecl*[LookupIsMap - 1];
+ LookupPtr.setPointer(Array);
+ } else {
+ Array = static_cast<NamedDecl **>(LookupPtr.getPointer());
+ }
+
+ // We always keep declarations of the same name next to each other
+ // in the array, so that it is easy to return multiple results
+ // from lookup(). There will be zero, one, or two declarations of
+ // the same name.
+ unsigned Match;
+ for (Match = 0; Match < Size; ++Match) {
+ if (Array[Match]->getDeclName() == D->getDeclName())
+ break;
+ }
+
+ if (Match < Size) {
+ // We found another declaration with the same name. If it's also
+ // in the same identifier namespace, update the declaration in
+ // place.
+ Decl::IdentifierNamespace NS = D->getIdentifierNamespace();
+ if (Array[Match]->getIdentifierNamespace() == NS) {
+ Array[Match] = D;
+ return;
+ }
+ if (Match + 1 < Size && Array[Match + 1]->getIdentifierNamespace() == NS) {
+ Array[Match + 1] = D;
+ return;
+ }
+
+ // If there is an existing declaration in the namespace of
+ // ordinary identifiers, then it must precede the tag
+ // declaration for C++ name lookup to operate properly. Therefore,
+ // if our match is an ordinary name and the new name is in the
+ // tag namespace, we'll insert the new declaration after it.
+ if (Match < Size && (NS == Decl::IDNS_Tag) &&
+ (Array[Match]->getIdentifierNamespace() & Decl::IDNS_Ordinary))
+ ++Match;
+ }
+
+ if (Size < LookupIsMap - 1) {
+ // The new declaration will fit in the array. Insert the new
+ // declaration at the position Match in the array.
+ for (unsigned Idx = Size; Idx > Match; --Idx)
+ Array[Idx] = Array[Idx-1];
+
+ Array[Match] = D;
+ LookupPtr.setInt(Size + 1);
+ return;
+ }
+
+ // We've reached capacity in this array. Create a map and copy in
+ // all of the declarations that were stored in the array.
+ StoredDeclsMap *Map = new StoredDeclsMap(16);
+ LookupPtr.setPointer(Map);
+ LookupPtr.setInt(LookupIsMap);
+ for (unsigned Idx = 0; Idx < LookupIsMap - 1; ++Idx)
+ insertImpl(Array[Idx]);
+ delete [] Array;
+
+ // Fall through to perform insertion into the map.
+ }
+
+ // Insert this declaration into the map.
+ StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
+ StoredDeclsMap::iterator Pos = Map->find(D->getDeclName());
+ unsigned IndexOfD = D->getIdentifierNamespace() & Decl::IDNS_Ordinary? 0 : 1;
+
+ if (Pos == Map->end()) {
+ // Put this declaration into the appropriate slot.
+ TwoNamedDecls Val;
+ Val.Decls[0] = 0;
+ Val.Decls[1] = 0;
+ Val.Decls[IndexOfD] = D;
+ Pos = Map->insert(std::make_pair(D->getDeclName(),Val)).first;
+ } else {
+ Pos->second.Decls[IndexOfD] = D;
+ }
+}
Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Thu Dec 11 10:49:14 2008
@@ -36,16 +36,9 @@
return new (Mem) NonTypeTemplateParmDecl(DC, L, Id, T, TypeSpecStartLoc);
}
-CXXFieldDecl *CXXFieldDecl::Create(ASTContext &C, CXXRecordDecl *RD,
- SourceLocation L, IdentifierInfo *Id,
- QualType T, bool Mut, Expr *BW) {
- void *Mem = C.getAllocator().Allocate<CXXFieldDecl>();
- return new (Mem) CXXFieldDecl(RD, L, Id, T, Mut, BW);
-}
-
CXXRecordDecl::CXXRecordDecl(TagKind TK, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id)
- : RecordDecl(CXXRecord, TK, DC, L, Id), DeclContext(CXXRecord),
+ : RecordDecl(CXXRecord, TK, DC, L, Id),
UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
Aggregate(true), Polymorphic(false), Bases(0), NumBases(0),
Constructors(DC, DeclarationName()),
@@ -74,11 +67,6 @@
if (isDefinition())
Destructor->Destroy(C);
- for (OverloadedFunctionDecl::function_iterator func
- = Conversions.function_begin();
- func != Conversions.function_end(); ++func)
- (*func)->Destroy(C);
-
RecordDecl::Destroy(C);
}
@@ -176,7 +164,7 @@
}
CXXBaseOrMemberInitializer::
-CXXBaseOrMemberInitializer(CXXFieldDecl *Member, Expr **Args, unsigned NumArgs)
+CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs)
: Args(0), NumArgs(0) {
BaseOrMember = reinterpret_cast<uintptr_t>(Member);
assert((BaseOrMember & 0x01) == 0 && "Invalid member pointer");
Modified: cfe/trunk/lib/AST/DeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclObjC.cpp (original)
+++ cfe/trunk/lib/AST/DeclObjC.cpp Thu Dec 11 10:49:14 2008
@@ -95,10 +95,10 @@
ObjCAtDefsFieldDecl
-*ObjCAtDefsFieldDecl::Create(ASTContext &C, SourceLocation L,
+*ObjCAtDefsFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType T, Expr *BW) {
void *Mem = C.getAllocator().Allocate<ObjCAtDefsFieldDecl>();
- return new (Mem) ObjCAtDefsFieldDecl(L, Id, T, BW);
+ return new (Mem) ObjCAtDefsFieldDecl(DC, L, Id, T, BW);
}
void ObjCAtDefsFieldDecl::Destroy(ASTContext& C) {
Modified: cfe/trunk/lib/AST/DeclSerialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclSerialization.cpp?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclSerialization.cpp (original)
+++ cfe/trunk/lib/AST/DeclSerialization.cpp Thu Dec 11 10:49:14 2008
@@ -120,11 +120,29 @@
//===----------------------------------------------------------------------===//
void DeclContext::EmitOutRec(Serializer& S) const {
- S.EmitPtr(DeclChain);
+ S.EmitInt(Decls.size());
+ for (decl_iterator D = decls_begin(); D != decls_end(); ++D) {
+ bool Owned = ((*D)->getLexicalDeclContext() == this &&
+ DeclKind != Decl::TranslationUnit &&
+ !isFunctionOrMethod());
+ S.EmitBool(Owned);
+ if (Owned)
+ S.EmitOwnedPtr(*D);
+ else
+ S.EmitPtr(*D);
+ }
}
void DeclContext::ReadOutRec(Deserializer& D, ASTContext& C) {
- D.ReadPtr(DeclChain);
+ unsigned NumDecls = D.ReadInt();
+ Decls.resize(NumDecls);
+ for (unsigned Idx = 0; Idx < NumDecls; ++Idx) {
+ bool Owned = D.ReadBool();
+ if (Owned)
+ Decls[Idx] = cast_or_null<ScopedDecl>(D.ReadOwnedPtr<Decl>(C));
+ else
+ D.ReadPtr<ScopedDecl>(Decls[Idx]);
+ }
}
//===----------------------------------------------------------------------===//
@@ -205,14 +223,12 @@
void ScopedDecl::EmitInRec(Serializer& S) const {
NamedDecl::EmitInRec(S);
- S.EmitPtr(getNext()); // From ScopedDecl.
S.EmitPtr(cast_or_null<Decl>(getDeclContext())); // From ScopedDecl.
S.EmitPtr(cast_or_null<Decl>(getLexicalDeclContext())); // From ScopedDecl.
}
void ScopedDecl::ReadInRec(Deserializer& D, ASTContext& C) {
NamedDecl::ReadInRec(D, C);
- D.ReadPtr(Next); // From ScopedDecl.
assert(DeclCtx == 0);
@@ -394,8 +410,8 @@
void EnumDecl::EmitImpl(Serializer& S) const {
ScopedDecl::EmitInRec(S);
S.EmitBool(isDefinition());
- S.Emit(IntegerType);
- S.BatchEmitOwnedPtrs(getEnumConstantList(),getNextDeclarator());
+ S.Emit(IntegerType);
+ S.EmitOwnedPtr(getNextDeclarator());
}
EnumDecl* EnumDecl::CreateImpl(Deserializer& D, ASTContext& C) {
@@ -406,12 +422,7 @@
decl->setDefinition(D.ReadBool());
decl->IntegerType = QualType::ReadVal(D);
- Decl* next_declarator;
- Decl* Elist;
-
- D.BatchReadOwnedPtrs(Elist, next_declarator, C);
-
- decl->setDeclChain(cast_or_null<EnumConstantDecl>(Elist));
+ Decl* next_declarator = D.ReadOwnedPtr<Decl>(C);
decl->setNextDeclarator(cast_or_null<ScopedDecl>(next_declarator));
return decl;
@@ -451,14 +462,17 @@
//===----------------------------------------------------------------------===//
void FieldDecl::EmitImpl(Serializer& S) const {
+ S.EmitBool(Mutable);
S.Emit(getType());
- NamedDecl::EmitInRec(S);
+ ScopedDecl::EmitInRec(S);
S.EmitOwnedPtr(BitWidth);
}
FieldDecl* FieldDecl::CreateImpl(Deserializer& D, ASTContext& C) {
void *Mem = C.getAllocator().Allocate<FieldDecl>();
- FieldDecl* decl = new (Mem) FieldDecl(SourceLocation(), NULL, QualType(), 0);
+ FieldDecl* decl = new (Mem) FieldDecl(Field, 0, SourceLocation(), NULL,
+ QualType(), 0, false, 0);
+ decl->Mutable = D.ReadBool();
decl->DeclType.ReadBackpatch(D);
decl->ReadInRec(D, C);
decl->BitWidth = D.ReadOwnedPtr<Expr>(C);
@@ -579,13 +593,7 @@
ScopedDecl::EmitInRec(S);
S.EmitBool(isDefinition());
S.EmitBool(hasFlexibleArrayMember());
- S.EmitSInt(getNumMembers());
- if (getNumMembers() > 0) {
- assert (Members);
- S.BatchEmitOwnedPtrs((unsigned) getNumMembers(), (Decl**) &Members[0]);
- }
- else
- ScopedDecl::EmitOutRec(S);
+ ScopedDecl::EmitOutRec(S);
}
RecordDecl* RecordDecl::CreateImpl(Deserializer& D, ASTContext& C) {
@@ -597,17 +605,8 @@
decl->ScopedDecl::ReadInRec(D, C);
decl->setDefinition(D.ReadBool());
decl->setHasFlexibleArrayMember(D.ReadBool());
- decl->NumMembers = D.ReadSInt();
-
- if (decl->getNumMembers() > 0) {
- decl->Members = new FieldDecl*[(unsigned) decl->getNumMembers()];
-
- D.BatchReadOwnedPtrs((unsigned) decl->getNumMembers(),
- (Decl**) &decl->Members[0], C);
- }
- else
- decl->ScopedDecl::ReadOutRec(D, C);
-
+ decl->ScopedDecl::ReadOutRec(D, C);
+
return decl;
}
Modified: cfe/trunk/lib/AST/DeclarationName.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclarationName.cpp?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclarationName.cpp (original)
+++ cfe/trunk/lib/AST/DeclarationName.cpp Thu Dec 11 10:49:14 2008
@@ -311,3 +311,9 @@
return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
}
+unsigned
+llvm::DenseMapInfo<clang::DeclarationName>::
+getHashValue(clang::DeclarationName N) {
+ return DenseMapInfo<void*>::getHashValue(N.getAsOpaquePtr());
+}
+
Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Thu Dec 11 10:49:14 2008
@@ -353,7 +353,7 @@
= dyn_cast<NonTypeTemplateParmDecl>(Decl))
return NTTParm->getType()->isReferenceType();
- return isa<VarDecl>(Decl) || isa<CXXFieldDecl>(Decl) ||
+ return isa<VarDecl>(Decl) || isa<FieldDecl>(Decl) ||
// C++ 3.10p2: An lvalue refers to an object or function.
(Ctx.getLangOptions().CPlusPlus &&
(isa<FunctionDecl>(Decl) || isa<OverloadedFunctionDecl>(Decl)));
@@ -1222,10 +1222,15 @@
const ASTRecordLayout &RL = C.getASTRecordLayout(RD);
FieldDecl *FD = ME->getMemberDecl();
- // FIXME: This is linear time.
- unsigned i = 0, e = 0;
- for (i = 0, e = RD->getNumMembers(); i != e; i++) {
- if (RD->getMember(i) == FD)
+ // FIXME: This is linear time. And the fact that we're indexing
+ // into the layout by position in the record means that we're
+ // either stuck numbering the fields in the AST or we have to keep
+ // the linear search (yuck and yuck).
+ unsigned i = 0;
+ for (RecordDecl::field_iterator Field = RD->field_begin(),
+ FieldEnd = RD->field_end();
+ Field != FieldEnd; (void)++Field, ++i) {
+ if (*Field == FD)
break;
}
Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Thu Dec 11 10:49:14 2008
@@ -156,9 +156,11 @@
FieldDecl *FD = E->getMemberDecl();
// FIXME: This is linear time.
- unsigned i = 0, e = 0;
- for (i = 0, e = RD->getNumMembers(); i != e; i++) {
- if (RD->getMember(i) == FD)
+ unsigned i = 0;
+ for (RecordDecl::field_iterator Field = RD->field_begin(),
+ FieldEnd = RD->field_end();
+ Field != FieldEnd; (void)++Field, ++i) {
+ if (*Field == FD)
break;
}
Modified: cfe/trunk/lib/Analysis/RegionStore.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/RegionStore.cpp?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/RegionStore.cpp (original)
+++ cfe/trunk/lib/Analysis/RegionStore.cpp Thu Dec 11 10:49:14 2008
@@ -433,8 +433,13 @@
llvm::ImmutableList<SVal> StructVal = getBasicVals().getEmptySValList();
- for (int i = RD->getNumMembers() - 1; i >= 0; --i) {
- FieldRegion* FR = MRMgr.getFieldRegion(RD->getMember(i), R);
+ for (DeclContext::reverse_decl_iterator Mem = RD->decls_rbegin();
+ Mem != RD->decls_rend(); ++Mem) {
+ FieldDecl *FD = dyn_cast<FieldDecl>(*Mem);
+ if (!FD)
+ continue;
+
+ FieldRegion* FR = MRMgr.getFieldRegion(FD, R);
RegionBindingsTy B(static_cast<const RegionBindingsTy::TreeTy*>(store));
RegionBindingsTy::data_type* data = B.lookup(FR);
Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Thu Dec 11 10:49:14 2008
@@ -289,10 +289,11 @@
llvm::SmallVector<llvm::DIDescriptor, 32> Enumerators;
// Create DIEnumerator elements for each enumerator.
- for (EnumConstantDecl *Elt = Decl->getEnumConstantList(); Elt;
- Elt = dyn_cast_or_null<EnumConstantDecl>(Elt->getNextDeclarator())) {
- Enumerators.push_back(DebugFactory.CreateEnumerator(Elt->getNameAsString(),
- Elt->getInitVal().getZExtValue()));
+ for (EnumDecl::enumerator_iterator Enum = Decl->enumerator_begin(),
+ EnumEnd = Decl->enumerator_end();
+ Enum != EnumEnd; ++Enum) {
+ Enumerators.push_back(DebugFactory.CreateEnumerator(Enum->getNameAsString(),
+ Enum->getInitVal().getZExtValue()));
}
// Return a CompositeType for the enum itself.
Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Thu Dec 11 10:49:14 2008
@@ -434,20 +434,24 @@
// the optimizer, especially with bitfields.
unsigned NumInitElements = E->getNumInits();
RecordDecl *SD = E->getType()->getAsRecordType()->getDecl();
- unsigned NumMembers = SD->getNumMembers() - SD->hasFlexibleArrayMember();
unsigned CurInitVal = 0;
bool isUnion = E->getType()->isUnionType();
// Here we iterate over the fields; this makes it simpler to both
// default-initialize fields and skip over unnamed fields.
- for (unsigned CurFieldNo = 0; CurFieldNo != NumMembers; ++CurFieldNo) {
- FieldDecl *CurField = SD->getMember(CurFieldNo);
- if (CurField->getIdentifier() == 0) {
+ for (RecordDecl::field_iterator Field = SD->field_begin(),
+ FieldEnd = SD->field_end();
+ Field != FieldEnd; ++Field) {
+ // We're done once we hit the flexible array member
+ if (Field->getType()->isIncompleteArrayType())
+ break;
+
+ if (Field->getIdentifier() == 0) {
// Initializers can't initialize unnamed fields, e.g. "int : 20;"
continue;
}
// FIXME: volatility
- LValue FieldLoc = CGF.EmitLValueForField(DestPtr, CurField, isUnion,0);
+ LValue FieldLoc = CGF.EmitLValueForField(DestPtr, *Field, isUnion,0);
if (CurInitVal < NumInitElements) {
// Store the initializer into the field
// This will probably have to get a bit smarter when we support
@@ -455,7 +459,7 @@
EmitInitializationToLValue(E->getInit(CurInitVal++), FieldLoc);
} else {
// We're out of initalizers; default-initialize to null
- EmitNullInitializationToLValue(FieldLoc, CurField->getType());
+ EmitNullInitializationToLValue(FieldLoc, Field->getType());
}
// Unions only initialize one field.
Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Thu Dec 11 10:49:14 2008
@@ -187,16 +187,17 @@
unsigned EltNo = 0; // Element no in ILE
int FieldNo = 0; // Field no in RecordDecl
bool RewriteType = false;
- while (EltNo < ILE->getNumInits() && FieldNo < RD->getNumMembers()) {
- FieldDecl* curField = RD->getMember(FieldNo);
+ for (RecordDecl::field_iterator Field = RD->field_begin(),
+ FieldEnd = RD->field_end();
+ EltNo < ILE->getNumInits() && Field != FieldEnd; ++Field) {
FieldNo++;
- if (!curField->getIdentifier())
+ if (!Field->getIdentifier())
continue;
- if (curField->isBitField()) {
- InsertBitfieldIntoStruct(Elts, curField, ILE->getInit(EltNo));
+ if (Field->isBitField()) {
+ InsertBitfieldIntoStruct(Elts, *Field, ILE->getInit(EltNo));
} else {
- unsigned FieldNo = CGM.getTypes().getLLVMFieldNo(curField);
+ unsigned FieldNo = CGM.getTypes().getLLVMFieldNo(*Field);
llvm::Constant *C = CGM.EmitConstantExpr(ILE->getInit(EltNo), CGF);
RewriteType |= (C->getType() != Elts[FieldNo]->getType());
Elts[FieldNo] = C;
@@ -223,8 +224,10 @@
// Find the field decl we're initializing, if any
int FieldNo = 0; // Field no in RecordDecl
FieldDecl* curField = 0;
- while (FieldNo < RD->getNumMembers()) {
- curField = RD->getMember(FieldNo);
+ for (RecordDecl::field_iterator Field = RD->field_begin(),
+ FieldEnd = RD->field_end();
+ Field != FieldEnd; ++Field) {
+ curField = *Field;
FieldNo++;
if (curField->getIdentifier())
break;
Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Thu Dec 11 10:49:14 2008
@@ -2373,12 +2373,15 @@
RecordDecl *RD = RecordDecl::Create(Ctx, TagDecl::TK_struct, 0,
SourceLocation(),
&Ctx.Idents.get("_objc_super"));
- FieldDecl *FieldDecls[2];
- FieldDecls[0] = FieldDecl::Create(Ctx, SourceLocation(), 0,
- Ctx.getObjCIdType());
- FieldDecls[1] = FieldDecl::Create(Ctx, SourceLocation(), 0,
- Ctx.getObjCClassType());
- RD->defineBody(Ctx, FieldDecls, 2);
+ RD->addDecl(Ctx,
+ FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
+ Ctx.getObjCIdType(), 0, false, 0),
+ true);
+ RD->addDecl(Ctx,
+ FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
+ Ctx.getObjCClassType(), 0, false, 0),
+ true);
+ RD->completeDefinition(Ctx);
SuperCTy = Ctx.getTagDeclType(RD);
SuperPtrCTy = Ctx.getPointerType(SuperCTy);
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Thu Dec 11 10:49:14 2008
@@ -775,21 +775,20 @@
static void appendFieldAndPadding(CodeGenModule &CGM,
std::vector<llvm::Constant*>& Fields,
- int FieldNo, llvm::Constant* Field,
+ FieldDecl *FieldD, FieldDecl *NextFieldD,
+ llvm::Constant* Field,
RecordDecl* RD, const llvm::StructType *STy)
{
// Append the field.
Fields.push_back(Field);
- int StructFieldNo =
- CGM.getTypes().getLLVMFieldNo(RD->getMember(FieldNo));
+ int StructFieldNo = CGM.getTypes().getLLVMFieldNo(FieldD);
int NextStructFieldNo;
- if (FieldNo + 1 == RD->getNumMembers()) {
+ if (!NextFieldD) {
NextStructFieldNo = STy->getNumElements();
} else {
- NextStructFieldNo =
- CGM.getTypes().getLLVMFieldNo(RD->getMember(FieldNo + 1));
+ NextStructFieldNo = CGM.getTypes().getLLVMFieldNo(NextFieldD);
}
// Append padding
@@ -841,29 +840,38 @@
cast<llvm::StructType>(getTypes().ConvertType(CFTy));
std::vector<llvm::Constant*> Fields;
-
-
+ RecordDecl::field_iterator Field = CFRD->field_begin();
+
// Class pointer.
- appendFieldAndPadding(*this, Fields, 0, CFConstantStringClassRef, CFRD, STy);
+ FieldDecl *CurField = *Field++;
+ FieldDecl *NextField = *Field++;
+ appendFieldAndPadding(*this, Fields, CurField, NextField,
+ CFConstantStringClassRef, CFRD, STy);
// Flags.
+ CurField = NextField;
+ NextField = *Field++;
const llvm::Type *Ty = getTypes().ConvertType(getContext().UnsignedIntTy);
- appendFieldAndPadding(*this, Fields, 1, llvm::ConstantInt::get(Ty, 0x07C8),
- CFRD, STy);
+ appendFieldAndPadding(*this, Fields, CurField, NextField,
+ llvm::ConstantInt::get(Ty, 0x07C8), CFRD, STy);
// String pointer.
+ CurField = NextField;
+ NextField = *Field++;
llvm::Constant *C = llvm::ConstantArray::get(str);
C = new llvm::GlobalVariable(C->getType(), true,
llvm::GlobalValue::InternalLinkage,
C, ".str", &getModule());
- appendFieldAndPadding(*this, Fields, 2,
+ appendFieldAndPadding(*this, Fields, CurField, NextField,
llvm::ConstantExpr::getGetElementPtr(C, Zeros, 2),
CFRD, STy);
// String length.
+ CurField = NextField;
+ NextField = 0;
Ty = getTypes().ConvertType(getContext().LongTy);
- appendFieldAndPadding(*this, Fields, 3, llvm::ConstantInt::get(Ty, str.length()),
- CFRD, STy);
+ appendFieldAndPadding(*this, Fields, CurField, NextField,
+ llvm::ConstantInt::get(Ty, str.length()), CFRD, STy);
// The struct.
C = llvm::ConstantStruct::get(STy, Fields);
Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTypes.cpp?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenTypes.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenTypes.cpp Thu Dec 11 10:49:14 2008
@@ -392,7 +392,7 @@
} else if (TD->isUnion()) {
// Just use the largest element of the union, breaking ties with the
// highest aligned member.
- if (RD->getNumMembers() != 0) {
+ if (RD->field_begin() != RD->field_end()) {
RecordOrganizer RO(*this, *RD);
RO.layoutUnionFields(Context.getASTRecordLayout(RD));
@@ -478,16 +478,17 @@
uint64_t llvmSize = 0;
// FIXME: Make this a SmallVector
std::vector<const llvm::Type*> LLVMFields;
- int NumMembers = RD.getNumMembers();
- for (int curField = 0; curField < NumMembers; curField++) {
- const FieldDecl *FD = RD.getMember(curField);
+ unsigned curField = 0;
+ for (RecordDecl::field_iterator Field = RD.field_begin(),
+ FieldEnd = RD.field_end();
+ Field != FieldEnd; ++Field) {
uint64_t offset = RL.getFieldOffset(curField);
- const llvm::Type *Ty = CGT.ConvertTypeRecursive(FD->getType());
+ const llvm::Type *Ty = CGT.ConvertTypeRecursive(Field->getType());
uint64_t size = CGT.getTargetData().getABITypeSizeInBits(Ty);
- if (FD->isBitField()) {
- Expr *BitWidth = FD->getBitWidth();
+ if (Field->isBitField()) {
+ Expr *BitWidth = Field->getBitWidth();
llvm::APSInt FieldSize(32);
bool isBitField =
BitWidth->isIntegerConstantExpr(FieldSize, CGT.getContext());
@@ -498,8 +499,8 @@
// Bitfield field info is different from other field info;
// it actually ignores the underlying LLVM struct because
// there isn't any convenient mapping.
- CGT.addFieldInfo(FD, offset / size);
- CGT.addBitFieldInfo(FD, offset % size, BitFieldSize);
+ CGT.addFieldInfo(*Field, offset / size);
+ CGT.addBitFieldInfo(*Field, offset % size, BitFieldSize);
} else {
// Put the element into the struct. This would be simpler
// if we didn't bother, but it seems a bit too strange to
@@ -510,9 +511,10 @@
}
llvmSize += size;
- CGT.addFieldInfo(FD, LLVMFields.size());
+ CGT.addFieldInfo(*Field, LLVMFields.size());
LLVMFields.push_back(Ty);
}
+ ++curField;
}
while (llvmSize < RL.getSize()) {
@@ -528,21 +530,24 @@
/// corresponding llvm struct type. This should be invoked only after
/// all fields are added.
void RecordOrganizer::layoutUnionFields(const ASTRecordLayout &RL) {
- for (int curField = 0; curField < RD.getNumMembers(); curField++) {
- const FieldDecl *FD = RD.getMember(curField);
+ unsigned curField = 0;
+ for (RecordDecl::field_iterator Field = RD.field_begin(),
+ FieldEnd = RD.field_end();
+ Field != FieldEnd; ++Field) {
// The offset should usually be zero, but bitfields could be strange
uint64_t offset = RL.getFieldOffset(curField);
- if (FD->isBitField()) {
- Expr *BitWidth = FD->getBitWidth();
+ if (Field->isBitField()) {
+ Expr *BitWidth = Field->getBitWidth();
uint64_t BitFieldSize =
BitWidth->getIntegerConstantExprValue(CGT.getContext()).getZExtValue();
- CGT.addFieldInfo(FD, 0);
- CGT.addBitFieldInfo(FD, offset, BitFieldSize);
+ CGT.addFieldInfo(*Field, 0);
+ CGT.addBitFieldInfo(*Field, offset, BitFieldSize);
} else {
- CGT.addFieldInfo(FD, 0);
+ CGT.addFieldInfo(*Field, 0);
}
+ ++curField;
}
// This looks stupid, but it is correct in the sense that
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Thu Dec 11 10:49:14 2008
@@ -914,7 +914,7 @@
for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) {
FieldDeclarator &FD = FieldDeclarators[i];
// Install the declarator into the current TagDecl.
- DeclTy *Field = Actions.ActOnField(CurScope,
+ DeclTy *Field = Actions.ActOnField(CurScope, TagDecl,
DS.getSourceRange().getBegin(),
FD.D, FD.BitfieldSize);
FieldDecls.push_back(Field);
@@ -934,8 +934,8 @@
continue;
}
llvm::SmallVector<DeclTy*, 16> Fields;
- Actions.ActOnDefs(CurScope, Tok.getLocation(), Tok.getIdentifierInfo(),
- Fields);
+ Actions.ActOnDefs(CurScope, TagDecl, Tok.getLocation(),
+ Tok.getIdentifierInfo(), Fields);
FieldDecls.insert(FieldDecls.end(), Fields.begin(), Fields.end());
ConsumeToken();
ExpectAndConsume(tok::r_paren, diag::err_expected_rparen);
Modified: cfe/trunk/lib/Sema/CXXFieldCollector.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CXXFieldCollector.h?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/CXXFieldCollector.h (original)
+++ cfe/trunk/lib/Sema/CXXFieldCollector.h Thu Dec 11 10:49:14 2008
@@ -18,15 +18,15 @@
#include "llvm/ADT/SmallVector.h"
namespace clang {
- class CXXFieldDecl;
+ class FieldDecl;
/// CXXFieldCollector - Used to keep track of CXXFieldDecls during parsing of
/// C++ classes.
class CXXFieldCollector {
- /// Fields - Contains all CXXFieldDecls collected during parsing of a C++
+ /// Fields - Contains all FieldDecls collected during parsing of a C++
/// class. When a nested class is entered, its fields are appended to the
/// fields of its parent class, when it is exited its fields are removed.
- llvm::SmallVector<CXXFieldDecl*, 32> Fields;
+ llvm::SmallVector<FieldDecl*, 32> Fields;
/// FieldCount - Each entry represents the number of fields collected during
/// the parsing of a C++ class. When a nested class is entered, a new field
@@ -52,7 +52,7 @@
void StartClass() { FieldCount.push_back(0); }
/// Add - Called by Sema::ActOnCXXMemberDeclarator.
- void Add(CXXFieldDecl *D) {
+ void Add(FieldDecl *D) {
Fields.push_back(D);
++FieldCount.back();
}
@@ -62,7 +62,7 @@
/// getCurFields - Pointer to array of fields added to the currently parsed
/// class.
- CXXFieldDecl **getCurFields() { return &*(Fields.end() - getCurNumFields()); }
+ FieldDecl **getCurFields() { return &*(Fields.end() - getCurNumFields()); }
/// FinishClass - Called by Sema::ActOnFinishCXXClassDef.
void FinishClass() {
Modified: cfe/trunk/lib/Sema/IdentifierResolver.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/IdentifierResolver.cpp?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/IdentifierResolver.cpp (original)
+++ cfe/trunk/lib/Sema/IdentifierResolver.cpp Thu Dec 11 10:49:14 2008
@@ -51,9 +51,6 @@
DeclContext *IdentifierResolver::LookupContext::getContext(Decl *D) {
DeclContext *Ctx;
- if (CXXFieldDecl *FD = dyn_cast<CXXFieldDecl>(D))
- return FD->getParent();
-
if (EnumConstantDecl *EnumD = dyn_cast<EnumConstantDecl>(D)) {
Ctx = EnumD->getDeclContext()->getParent();
} else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D))
@@ -149,7 +146,7 @@
/// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
/// true if 'D' belongs to the given declaration context.
bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx,
- Scope *S) const {
+ ASTContext &Context, Scope *S) const {
if (Ctx->isFunctionOrMethod()) {
if (S->isDeclScope(D))
return true;
@@ -169,7 +166,7 @@
return false;
}
- return LookupContext(D) == LookupContext(Ctx);
+ return LookupContext(D) == LookupContext(Ctx->getPrimaryContext(Context));
}
/// AddDecl - Link the decl to its shadowed decl chain.
Modified: cfe/trunk/lib/Sema/IdentifierResolver.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/IdentifierResolver.h?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/IdentifierResolver.h (original)
+++ cfe/trunk/lib/Sema/IdentifierResolver.h Thu Dec 11 10:49:14 2008
@@ -208,7 +208,8 @@
/// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true
/// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
/// true if 'D' belongs to the given declaration context.
- bool isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S = 0) const;
+ bool isDeclInScope(Decl *D, DeclContext *Ctx, ASTContext &Context,
+ Scope *S = 0) const;
/// AddDecl - Link the decl to its shadowed decl chain.
void AddDecl(NamedDecl *D);
Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Thu Dec 11 10:49:14 2008
@@ -68,7 +68,7 @@
void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
TUScope = S;
- PushDeclContext(Context.getTranslationUnitDecl());
+ PushDeclContext(S, Context.getTranslationUnitDecl());
if (!PP.getLangOptions().ObjC1) return;
// Synthesize "typedef struct objc_selector *SEL;"
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Thu Dec 11 10:49:14 2008
@@ -300,10 +300,10 @@
IdentifierInfo *Name, SourceLocation NameLoc,
AttributeList *Attr);
- virtual void ActOnDefs(Scope *S, SourceLocation DeclStart,
+ virtual void ActOnDefs(Scope *S, DeclTy *TagD, SourceLocation DeclStart,
IdentifierInfo *ClassName,
llvm::SmallVectorImpl<DeclTy*> &Decls);
- virtual DeclTy *ActOnField(Scope *S, SourceLocation DeclStart,
+ virtual DeclTy *ActOnField(Scope *S, DeclTy *TagD, SourceLocation DeclStart,
Declarator &D, ExprTy *BitfieldWidth);
virtual DeclTy *ActOnIvar(Scope *S, SourceLocation DeclStart,
@@ -326,7 +326,7 @@
DeclContext *getContainingDC(DeclContext *DC);
/// Set the current declaration context until it gets popped.
- void PushDeclContext(DeclContext *DC);
+ void PushDeclContext(Scope *S, DeclContext *DC);
void PopDeclContext();
/// getCurFunctionDecl - If inside of a function body, this returns a pointer
@@ -351,7 +351,7 @@
/// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
/// true if 'D' belongs to the given declaration context.
bool isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S = 0) {
- return IdResolver.isDeclInScope(D, Ctx, S);
+ return IdResolver.isDeclInScope(D, Ctx, Context, S);
}
/// Subroutines of ActOnDeclarator().
@@ -478,7 +478,8 @@
/// More parsing and symbol table subroutines...
Decl *LookupDecl(DeclarationName Name, unsigned NSI, Scope *S,
const DeclContext *LookupCtx = 0,
- bool enableLazyBuiltinCreation = true);
+ bool enableLazyBuiltinCreation = true,
+ bool LookInParent = true);
ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *Id);
ScopedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
Scope *S);
Modified: cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp Thu Dec 11 10:49:14 2008
@@ -20,7 +20,25 @@
namespace {
Decl *LookupNestedName(DeclContext *LookupCtx, bool LookInParentCtx,
- DeclarationName Name, bool &IdIsUndeclared) {
+ DeclarationName Name, bool &IdIsUndeclared,
+ ASTContext &Context) {
+ if (LookupCtx && !LookInParentCtx) {
+ IdIsUndeclared = true;
+ for (DeclContext::lookup_const_result I = LookupCtx->lookup(Context, Name);
+ I.first != I.second; ++I.first) {
+ IdIsUndeclared = false;
+ if (((*I.first)->getIdentifierNamespace() & Decl::IDNS_Tag) &&
+ !isa<EnumDecl>(*I.first))
+ return *I.first;
+ }
+
+ return 0;
+ }
+
+ // FIXME: Decouple this from the IdentifierResolver so that we can
+ // deal with lookups into the semantic parent contexts that aren't
+ // lexical parent contexts.
+
IdentifierResolver::iterator
I = IdentifierResolver::begin(Name, LookupCtx, LookInParentCtx),
E = IdentifierResolver::end();
@@ -73,10 +91,11 @@
bool IdIsUndeclared;
if (DC)
- SD = LookupNestedName(DC, false/*LookInParentCtx*/, &II, IdIsUndeclared);
+ SD = LookupNestedName(DC, false/*LookInParentCtx*/, &II, IdIsUndeclared,
+ Context);
else
SD = LookupNestedName(CurContext, true/*LookInParent*/, &II,
- IdIsUndeclared);
+ IdIsUndeclared, Context);
if (SD) {
if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Dec 11 10:49:14 2008
@@ -74,14 +74,16 @@
return DC->getLexicalParent();
}
-void Sema::PushDeclContext(DeclContext *DC) {
+void Sema::PushDeclContext(Scope *S, DeclContext *DC) {
assert(getContainingDC(DC) == CurContext &&
"The next DeclContext should be lexically contained in the current one.");
CurContext = DC;
+ S->setEntity(DC);
}
void Sema::PopDeclContext() {
assert(CurContext && "DeclContext imbalance!");
+
CurContext = getContainingDC(CurContext);
}
@@ -97,53 +99,90 @@
// in this case the class name or enumeration name is hidden.
if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
// We are pushing the name of a tag (enum or class).
- IdentifierResolver::iterator
- I = IdResolver.begin(TD->getIdentifier(),
- TD->getDeclContext(), false/*LookInParentCtx*/);
- if (I != IdResolver.end() && isDeclInScope(*I, TD->getDeclContext(), S)) {
- // There is already a declaration with the same name in the same
- // scope. It must be found before we find the new declaration,
- // so swap the order on the shadowed declaration chain.
-
- IdResolver.AddShadowedDecl(TD, *I);
- return;
+ if (CurContext == TD->getDeclContext()) {
+ // We're pushing the tag into the current context, which might
+ // require some reshuffling in the identifier resolver.
+ IdentifierResolver::iterator
+ I = IdResolver.begin(TD->getIdentifier(), CurContext,
+ false/*LookInParentCtx*/);
+ if (I != IdResolver.end()) {
+ // There is already a declaration with the same name in the same
+ // scope. It must be found before we find the new declaration,
+ // so swap the order on the shadowed declaration chain.
+ IdResolver.AddShadowedDecl(TD, *I);
+
+ // Add this declaration to the current context.
+ CurContext->addDecl(Context, TD);
+
+ return;
+ }
}
} else if (getLangOptions().CPlusPlus && isa<FunctionDecl>(D)) {
- FunctionDecl *FD = cast<FunctionDecl>(D);
// We are pushing the name of a function, which might be an
// overloaded name.
- IdentifierResolver::iterator
- I = IdResolver.begin(FD->getDeclName(),
- FD->getDeclContext(), false/*LookInParentCtx*/);
- if (I != IdResolver.end() &&
- IdResolver.isDeclInScope(*I, FD->getDeclContext(), S) &&
- (isa<OverloadedFunctionDecl>(*I) || isa<FunctionDecl>(*I))) {
- // There is already a declaration with the same name in the same
- // scope. It must be a function or an overloaded function.
- OverloadedFunctionDecl* Ovl = dyn_cast<OverloadedFunctionDecl>(*I);
+ FunctionDecl *FD = cast<FunctionDecl>(D);
+ Decl *Prev = LookupDecl(FD->getDeclName(), Decl::IDNS_Ordinary, S,
+ FD->getDeclContext(), false, false);
+ if (Prev && (isa<OverloadedFunctionDecl>(Prev) || isa<FunctionDecl>(Prev))) {
+ // There is already a declaration with the same name in
+ // the same scope. It must be a function or an overloaded
+ // function.
+ OverloadedFunctionDecl* Ovl = dyn_cast<OverloadedFunctionDecl>(Prev);
if (!Ovl) {
// We haven't yet overloaded this function. Take the existing
// FunctionDecl and put it into an OverloadedFunctionDecl.
Ovl = OverloadedFunctionDecl::Create(Context,
FD->getDeclContext(),
FD->getDeclName());
- Ovl->addOverload(dyn_cast<FunctionDecl>(*I));
+ Ovl->addOverload(dyn_cast<FunctionDecl>(Prev));
- // Remove the name binding to the existing FunctionDecl...
- IdResolver.RemoveDecl(*I);
-
- // ... and put the OverloadedFunctionDecl in its place.
+ // If there is an name binding for the existing FunctionDecl,
+ // remove it.
+ for (IdentifierResolver::iterator I
+ = IdResolver.begin(FD->getDeclName(), FD->getDeclContext(),
+ false/*LookInParentCtx*/);
+ I != IdResolver.end(); ++I) {
+ if (*I == Prev) {
+ IdResolver.RemoveDecl(*I);
+ S->RemoveDecl(*I);
+ break;
+ }
+ }
+
+ // Add the name binding for the OverloadedFunctionDecl.
IdResolver.AddDecl(Ovl);
+
+ // Update the context with the newly-created overloaded
+ // function set.
+ FD->getDeclContext()->insert(Context, Ovl);
+
+ S->AddDecl(Ovl);
}
+ // We added this function declaration to the scope earlier, but
+ // we don't want it there because it is part of the overloaded
+ // function declaration.
+ S->RemoveDecl(FD);
+
// We have an OverloadedFunctionDecl. Add the new FunctionDecl
// to its list of overloads.
Ovl->addOverload(FD);
- return;
+ // Add this new function declaration to the declaration context.
+ CurContext->addDecl(Context, FD, false);
+
+ return;
}
}
+ if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D))
+ CurContext->addDecl(Context, SD);
+ else {
+ // Other kinds of declarations don't currently have a context
+ // where they need to be inserted.
+ }
+
+
IdResolver.AddDecl(D);
}
@@ -157,25 +196,13 @@
Decl *TmpD = static_cast<Decl*>(*I);
assert(TmpD && "This decl didn't get pushed??");
- if (isa<CXXFieldDecl>(TmpD)) continue;
+ assert(isa<NamedDecl>(TmpD) && "Decl isn't NamedDecl?");
+ NamedDecl *D = cast<NamedDecl>(TmpD);
- assert(isa<ScopedDecl>(TmpD) && "Decl isn't ScopedDecl?");
- ScopedDecl *D = cast<ScopedDecl>(TmpD);
-
- IdentifierInfo *II = D->getIdentifier();
- if (!II) continue;
-
- // We only want to remove the decls from the identifier decl chains for
- // local scopes, when inside a function/method.
- // However, we *always* remove template parameters, since they are
- // purely lexically scoped (and can never be found by qualified
- // name lookup).
- if (S->getFnParent() != 0 || isa<TemplateTypeParmDecl>(D))
- IdResolver.RemoveDecl(D);
-
- // Chain this decl to the containing DeclContext.
- D->setNext(CurContext->getDeclChain());
- CurContext->setDeclChain(D);
+ if (!D->getDeclName()) continue;
+
+ // Remove this name from our lexical scope.
+ IdResolver.RemoveDecl(D);
}
}
@@ -193,21 +220,76 @@
/// namespace.
Decl *Sema::LookupDecl(DeclarationName Name, unsigned NSI, Scope *S,
const DeclContext *LookupCtx,
- bool enableLazyBuiltinCreation) {
+ bool enableLazyBuiltinCreation,
+ bool LookInParent) {
if (!Name) return 0;
unsigned NS = NSI;
if (getLangOptions().CPlusPlus && (NS & Decl::IDNS_Ordinary))
NS |= Decl::IDNS_Tag;
- IdentifierResolver::iterator
- I = LookupCtx ? IdResolver.begin(Name, LookupCtx, false/*LookInParentCtx*/)
- : IdResolver.begin(Name, CurContext, true/*LookInParentCtx*/);
- // Scan up the scope chain looking for a decl that matches this identifier
- // that is in the appropriate namespace. This search should not take long, as
- // shadowing of names is uncommon, and deep shadowing is extremely uncommon.
- for (; I != IdResolver.end(); ++I)
- if ((*I)->getIdentifierNamespace() & NS)
- return *I;
+ if (LookupCtx) {
+ assert(getLangOptions().CPlusPlus && "No qualified name lookup in C");
+
+ // Perform qualified name lookup into the LookupCtx.
+ // FIXME: Will need to look into base classes and such.
+ for (DeclContext::lookup_const_result I = LookupCtx->lookup(Context, Name);
+ I.first != I.second; ++I.first)
+ if ((*I.first)->getIdentifierNamespace() & NS)
+ return *I.first;
+ } else if (getLangOptions().CPlusPlus &&
+ (NS & (Decl::IDNS_Ordinary | Decl::IDNS_Tag))) {
+ // Name lookup for ordinary names and tag names in C++ requires
+ // looking into scopes that aren't strictly lexical, and
+ // therefore we walk through the context as well as walking
+ // through the scopes.
+ IdentifierResolver::iterator
+ I = IdResolver.begin(Name, CurContext, true/*LookInParentCtx*/),
+ IEnd = IdResolver.end();
+ for (; S; S = S->getParent()) {
+ // Check whether the IdResolver has anything in this scope.
+ // FIXME: The isDeclScope check could be expensive. Can we do better?
+ for (; I != IEnd && S->isDeclScope(*I); ++I)
+ if ((*I)->getIdentifierNamespace() & NS)
+ return *I;
+
+ // If there is an entity associated with this scope, it's a
+ // DeclContext. We might need to perform qualified lookup into
+ // it.
+ DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity());
+ while (Ctx && Ctx->isFunctionOrMethod())
+ Ctx = Ctx->getParent();
+ while (Ctx && (Ctx->isNamespace() || Ctx->isCXXRecord())) {
+ // Look for declarations of this name in this scope.
+ for (DeclContext::lookup_const_result I = Ctx->lookup(Context, Name);
+ I.first != I.second; ++I.first) {
+ // FIXME: Cache this result in the IdResolver
+ if ((*I.first)->getIdentifierNamespace() & NS)
+ return *I.first;
+ }
+
+ Ctx = Ctx->getParent();
+ }
+
+ if (!LookInParent)
+ return 0;
+ }
+ } else {
+ // Unqualified name lookup for names in our lexical scope. This
+ // name lookup suffices when all of the potential names are known
+ // to have been pushed onto the IdResolver, as happens in C
+ // (always) and in C++ for names in the "label" namespace.
+ assert(!LookupCtx && "Can't perform qualified name lookup here");
+ IdentifierResolver::iterator I
+ = IdResolver.begin(Name, CurContext, LookInParent);
+
+ // Scan up the scope chain looking for a decl that matches this
+ // identifier that is in the appropriate namespace. This search
+ // should not take long, as shadowing of names is uncommon, and
+ // deep shadowing is extremely uncommon.
+ for (; I != IdResolver.end(); ++I)
+ if ((*I)->getIdentifierNamespace() & NS)
+ return *I;
+ }
// If we didn't find a use of this identifier, and if the identifier
// corresponds to a compiler builtin, create the decl object for the builtin
@@ -826,7 +908,8 @@
// The scope passed in may not be a decl scope. Zip up the scope tree until
// we find one that is.
- while ((S->getFlags() & Scope::DeclScope) == 0)
+ while ((S->getFlags() & Scope::DeclScope) == 0 ||
+ (S->getFlags() & Scope::TemplateParamScope) != 0)
S = S->getParent();
DeclContext *DC;
@@ -854,6 +937,7 @@
// No previous declaration in the qualifying scope.
Diag(D.getIdentifierLoc(), diag::err_typecheck_no_member)
<< Name << D.getCXXScopeSpec().getRange();
+ InvalidDecl = true;
} else if (!CurContext->Encloses(DC)) {
// The qualifying scope doesn't enclose the original declaration.
// Emit diagnostic based on current scope.
@@ -865,6 +949,7 @@
Diag(L, diag::err_invalid_declarator_scope)
<< Name << cast<NamedDecl>(DC)->getDeclName() << R;
}
+ InvalidDecl = true;
}
}
@@ -1127,23 +1212,42 @@
if (OldDecl == PrevDecl) {
// Remove the name binding for the previous
- // declaration. We'll add the binding back later, but then
- // it will refer to the new declaration (which will
- // contain more information).
- IdResolver.RemoveDecl(cast<NamedDecl>(PrevDecl));
+ // declaration.
+ if (S->isDeclScope(PrevDecl)) {
+ IdResolver.RemoveDecl(cast<NamedDecl>(PrevDecl));
+ S->RemoveDecl(PrevDecl);
+ }
+
+ // Introduce the new binding for this declaration.
+ IdResolver.AddDecl(NewFD);
+ if (getLangOptions().CPlusPlus && NewFD->getParent())
+ NewFD->getParent()->insert(Context, NewFD);
+
+ // Add the redeclaration to the current scope, since we'll
+ // be skipping PushOnScopeChains.
+ S->AddDecl(NewFD);
} else {
// We need to update the OverloadedFunctionDecl with the
// latest declaration of this function, so that name
// lookup will always refer to the latest declaration of
// this function.
*MatchedDecl = NewFD;
+ }
- // Add the redeclaration to the current scope, since we'll
- // be skipping PushOnScopeChains.
- S->AddDecl(NewFD);
+ if (getLangOptions().CPlusPlus) {
+ // Add this declaration to the current context.
+ CurContext->addDecl(Context, NewFD, false);
- return NewFD;
+ // Check default arguments now that we have merged decls.
+ CheckCXXDefaultArguments(NewFD);
}
+
+ // Set the lexical context. If the declarator has a C++
+ // scope specifier, the lexical context will be different
+ // from the semantic context.
+ NewFD->setLexicalDeclContext(CurContext);
+
+ return NewFD;
}
}
}
@@ -2071,7 +2175,7 @@
parmDeclType = Context.getArrayDecayedType(parmDeclType);
} else if (parmDeclType->isFunctionType())
parmDeclType = Context.getPointerType(parmDeclType);
-
+
ParmVarDecl *New = ParmVarDecl::Create(Context, CurContext,
D.getIdentifierLoc(), II,
parmDeclType, StorageClass,
@@ -2079,9 +2183,11 @@
if (D.getInvalidType())
New->setInvalidDecl();
-
+
+ // Add the parameter declaration into this scope.
+ S->AddDecl(New);
if (II)
- PushOnScopeChains(New, S);
+ IdResolver.AddDecl(New);
ProcessDeclAttributes(New, D);
return New;
@@ -2133,7 +2239,7 @@
Diag(Definition->getLocation(), diag::note_previous_definition);
}
- PushDeclContext(FD);
+ PushDeclContext(FnBodyScope, FD);
// Check the validity of our function parameters
CheckParmsForFunctionDef(FD);
@@ -2573,17 +2679,19 @@
/// Collect the instance variables declared in an Objective-C object. Used in
/// the creation of structures from objects using the @defs directive.
-static void CollectIvars(ObjCInterfaceDecl *Class, ASTContext& Ctx,
+static void CollectIvars(ObjCInterfaceDecl *Class, RecordDecl *Record,
+ ASTContext& Ctx,
llvm::SmallVectorImpl<Sema::DeclTy*> &ivars) {
if (Class->getSuperClass())
- CollectIvars(Class->getSuperClass(), Ctx, ivars);
+ CollectIvars(Class->getSuperClass(), Record, Ctx, ivars);
// For each ivar, create a fresh ObjCAtDefsFieldDecl.
for (ObjCInterfaceDecl::ivar_iterator
I=Class->ivar_begin(), E=Class->ivar_end(); I!=E; ++I) {
ObjCIvarDecl* ID = *I;
- ivars.push_back(ObjCAtDefsFieldDecl::Create(Ctx, ID->getLocation(),
+ ivars.push_back(ObjCAtDefsFieldDecl::Create(Ctx, Record,
+ ID->getLocation(),
ID->getIdentifier(),
ID->getType(),
ID->getBitWidth()));
@@ -2592,7 +2700,7 @@
/// Called whenever @defs(ClassName) is encountered in the source. Inserts the
/// instance variables of ClassName into Decls.
-void Sema::ActOnDefs(Scope *S, SourceLocation DeclStart,
+void Sema::ActOnDefs(Scope *S, DeclTy *TagD, SourceLocation DeclStart,
IdentifierInfo *ClassName,
llvm::SmallVectorImpl<DeclTy*> &Decls) {
// Check that ClassName is a valid class
@@ -2602,7 +2710,17 @@
return;
}
// Collect the instance variables
- CollectIvars(Class, Context, Decls);
+ CollectIvars(Class, dyn_cast<RecordDecl>((Decl*)TagD), Context, Decls);
+
+ // Introduce all of these fields into the appropriate scope.
+ for (llvm::SmallVectorImpl<DeclTy*>::iterator D = Decls.begin();
+ D != Decls.end(); ++D) {
+ FieldDecl *FD = cast<FieldDecl>((Decl*)*D);
+ if (getLangOptions().CPlusPlus)
+ PushOnScopeChains(cast<FieldDecl>(FD), S);
+ else if (RecordDecl *Record = dyn_cast<RecordDecl>((Decl*)TagD))
+ Record->addDecl(Context, FD);
+ }
}
/// TryToFixInvalidVariablyModifiedType - Helper method to turn variable array
@@ -2657,12 +2775,13 @@
/// ActOnField - Each field of a struct/union/class is passed into this in order
/// to create a FieldDecl object for it.
-Sema::DeclTy *Sema::ActOnField(Scope *S,
+Sema::DeclTy *Sema::ActOnField(Scope *S, DeclTy *TagD,
SourceLocation DeclStart,
Declarator &D, ExprTy *BitfieldWidth) {
IdentifierInfo *II = D.getIdentifier();
Expr *BitWidth = (Expr*)BitfieldWidth;
SourceLocation Loc = DeclStart;
+ RecordDecl *Record = (RecordDecl *)TagD;
if (II) Loc = D.getIdentifierLoc();
// FIXME: Unnamed fields can be handled in various different ways, for
@@ -2699,22 +2818,24 @@
// FIXME: Chain fielddecls together.
FieldDecl *NewFD;
- if (getLangOptions().CPlusPlus) {
- // FIXME: Replace CXXFieldDecls with FieldDecls for simple structs.
- NewFD = CXXFieldDecl::Create(Context, cast<CXXRecordDecl>(CurContext),
- Loc, II, T,
- D.getDeclSpec().getStorageClassSpec() ==
- DeclSpec::SCS_mutable, BitWidth);
- if (II)
- PushOnScopeChains(NewFD, S);
- }
- else
- NewFD = FieldDecl::Create(Context, Loc, II, T, BitWidth);
-
+ // FIXME: We don't want CurContext for C, do we? No, we'll need some
+ // other way to determine the current RecordDecl.
+ NewFD = FieldDecl::Create(Context, Record,
+ Loc, II, T, BitWidth,
+ D.getDeclSpec().getStorageClassSpec() ==
+ DeclSpec::SCS_mutable,
+ /*PrevDecl=*/0);
+
ProcessDeclAttributes(NewFD, D);
if (D.getInvalidType() || InvalidDecl)
NewFD->setInvalidDecl();
+
+ if (II && getLangOptions().CPlusPlus)
+ PushOnScopeChains(NewFD, S);
+ else
+ Record->addDecl(Context, NewFD);
+
return NewFD;
}
@@ -2921,7 +3042,7 @@
// Okay, we successfully defined 'Record'.
if (Record) {
- Record->defineBody(Context, &RecFields[0], RecFields.size());
+ Record->completeDefinition(Context);
// If this is a C++ record, HandleTagDeclDefinition will be invoked in
// Sema::ActOnFinishCXXClassDef.
if (!isa<CXXRecordDecl>(Record))
@@ -3189,7 +3310,7 @@
ECD->setType(NewTy);
}
- Enum->defineElements(EltList, BestType);
+ Enum->completeDefinition(Context, BestType);
Consumer.HandleTagDeclDefinition(Enum);
}
Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Thu Dec 11 10:49:14 2008
@@ -904,8 +904,10 @@
// FIXME: This isn't supposed to be restricted to pointers, but otherwise
// we might silently generate incorrect code; see following code
- for (int i = 0; i < RD->getNumMembers(); i++) {
- if (!RD->getMember(i)->getType()->isPointerType()) {
+ for (RecordDecl::field_iterator Field = RD->field_begin(),
+ FieldEnd = RD->field_end();
+ Field != FieldEnd; ++Field) {
+ if (!Field->getType()->isPointerType()) {
S.Diag(Attr.getLoc(), diag::warn_transparent_union_nonpointer);
return;
}
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Dec 11 10:49:14 2008
@@ -382,7 +382,7 @@
/// definition, when on C++.
void Sema::ActOnStartCXXClassDef(Scope *S, DeclTy *D, SourceLocation LBrace) {
CXXRecordDecl *Dcl = cast<CXXRecordDecl>(static_cast<Decl *>(D));
- PushDeclContext(Dcl);
+ PushDeclContext(S, Dcl);
FieldCollector->StartClass();
if (Dcl->getIdentifier()) {
@@ -486,7 +486,8 @@
bool InvalidDecl = false;
if (isInstField)
- Member = static_cast<Decl*>(ActOnField(S, Loc, D, BitWidth));
+ Member = static_cast<Decl*>(ActOnField(S, cast<CXXRecordDecl>(CurContext),
+ Loc, D, BitWidth));
else
Member = static_cast<Decl*>(ActOnDeclarator(S, D, LastInGroup));
@@ -593,7 +594,7 @@
Member->setInvalidDecl();
if (isInstField) {
- FieldCollector->Add(cast<CXXFieldDecl>(Member));
+ FieldCollector->Add(cast<FieldDecl>(Member));
return LastInGroup;
}
return Member;
@@ -632,7 +633,10 @@
// mem-initializer-id for the hidden base class may be specified
// using a qualified name. ]
// Look for a member, first.
- CXXFieldDecl *Member = ClassDecl->getMember(MemberOrBase);
+ FieldDecl *Member = 0;
+ DeclContext::lookup_result Result = ClassDecl->lookup(Context, MemberOrBase);
+ if (Result.first != Result.second)
+ Member = dyn_cast<FieldDecl>(*Result.first);
// FIXME: Handle members of an anonymous union.
@@ -1251,43 +1255,42 @@
// in that declarative region, it is treated as an original-namespace-name.
Decl *PrevDecl =
- LookupDecl(II, Decl::IDNS_Tag | Decl::IDNS_Ordinary, DeclRegionScope, 0,
- /*enableLazyBuiltinCreation=*/false);
-
- if (PrevDecl && isDeclInScope(PrevDecl, CurContext, DeclRegionScope)) {
- if (NamespaceDecl *OrigNS = dyn_cast<NamespaceDecl>(PrevDecl)) {
- // This is an extended namespace definition.
- // Attach this namespace decl to the chain of extended namespace
- // definitions.
- NamespaceDecl *NextNS = OrigNS;
- while (NextNS->getNextNamespace())
- NextNS = NextNS->getNextNamespace();
-
- NextNS->setNextNamespace(Namespc);
- Namespc->setOriginalNamespace(OrigNS);
-
- // We won't add this decl to the current scope. We want the namespace
- // name to return the original namespace decl during a name lookup.
- } else {
- // This is an invalid name redefinition.
- Diag(Namespc->getLocation(), diag::err_redefinition_different_kind)
- << Namespc->getDeclName();
- Diag(PrevDecl->getLocation(), diag::note_previous_definition);
- Namespc->setInvalidDecl();
- // Continue on to push Namespc as current DeclContext and return it.
+ LookupDecl(II, Decl::IDNS_Tag | Decl::IDNS_Ordinary, DeclRegionScope, 0,
+ /*enableLazyBuiltinCreation=*/false,
+ /*LookupInParent=*/false);
+
+ if (NamespaceDecl *OrigNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl)) {
+ // This is an extended namespace definition.
+ // Attach this namespace decl to the chain of extended namespace
+ // definitions.
+ OrigNS->setNextNamespace(Namespc);
+ Namespc->setOriginalNamespace(OrigNS->getOriginalNamespace());
+
+ // Remove the previous declaration from the scope.
+ if (DeclRegionScope->isDeclScope(OrigNS)) {
+ IdResolver.RemoveDecl(OrigNS);
+ DeclRegionScope->RemoveDecl(OrigNS);
}
- } else {
- // This namespace name is declared for the first time.
- PushOnScopeChains(Namespc, DeclRegionScope);
- }
- }
- else {
+ } else if (PrevDecl) {
+ // This is an invalid name redefinition.
+ Diag(Namespc->getLocation(), diag::err_redefinition_different_kind)
+ << Namespc->getDeclName();
+ Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+ Namespc->setInvalidDecl();
+ // Continue on to push Namespc as current DeclContext and return it.
+ }
+
+ PushOnScopeChains(Namespc, DeclRegionScope);
+ } else {
// FIXME: Handle anonymous namespaces
}
// Although we could have an invalid decl (i.e. the namespace name is a
// redefinition), push it as current DeclContext and try to continue parsing.
- PushDeclContext(Namespc->getOriginalNamespace());
+ // FIXME: We should be able to push Namespc here, so that the
+ // each DeclContext for the namespace has the declarations
+ // that showed up in that particular namespace definition.
+ PushDeclContext(NamespcScope, Namespc);
return Namespc;
}
Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Thu Dec 11 10:49:14 2008
@@ -36,7 +36,7 @@
AddFactoryMethodToGlobalPool(MDecl);
// Allow all of Sema to see that we are entering a method definition.
- PushDeclContext(MDecl);
+ PushDeclContext(FnBodyScope, MDecl);
// Create Decl objects for each parameter, entrring them in the scope for
// binding to their use.
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Dec 11 10:49:14 2008
@@ -453,13 +453,13 @@
}
}
- if (CXXFieldDecl *FD = dyn_cast<CXXFieldDecl>(D)) {
+ if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext)) {
if (MD->isStatic())
// "invalid use of member 'x' in static member function"
return Diag(Loc, diag::err_invalid_member_use_in_static_method)
<< FD->getDeclName();
- if (cast<CXXRecordDecl>(MD->getParent()) != FD->getParent())
+ if (MD->getParent() != FD->getDeclContext())
// "invalid use of nonstatic data member 'x'"
return Diag(Loc, diag::err_invalid_non_static_member_use)
<< FD->getDeclName();
@@ -1231,20 +1231,28 @@
return Diag(OpLoc, diag::err_typecheck_incomplete_tag)
<< RDecl->getDeclName() << BaseExpr->getSourceRange();
// The record definition is complete, now make sure the member is valid.
- FieldDecl *MemberDecl = RDecl->getMember(&Member);
- if (!MemberDecl)
+ // FIXME: Qualified name lookup for C++ is a bit more complicated
+ // than this.
+ DeclContext::lookup_result Lookup = RDecl->lookup(Context, &Member);
+ if (Lookup.first == Lookup.second) {
return Diag(MemberLoc, diag::err_typecheck_no_member)
<< &Member << BaseExpr->getSourceRange();
+ }
+
+ FieldDecl *MemberDecl = dyn_cast<FieldDecl>(*Lookup.first);
+ if (!MemberDecl) {
+ unsigned DiagID = PP.getDiagnostics().getCustomDiagID(Diagnostic::Error,
+ "Clang only supports references to members");
+ return Diag(MemberLoc, DiagID);
+ }
// Figure out the type of the member; see C99 6.5.2.3p3
// FIXME: Handle address space modifiers
QualType MemberType = MemberDecl->getType();
unsigned combinedQualifiers =
MemberType.getCVRQualifiers() | BaseType.getCVRQualifiers();
- if (CXXFieldDecl *CXXMember = dyn_cast<CXXFieldDecl>(MemberDecl)) {
- if (CXXMember->isMutable())
- combinedQualifiers &= ~QualType::Const;
- }
+ if (MemberDecl->isMutable())
+ combinedQualifiers &= ~QualType::Const;
MemberType = MemberType.getQualifiedType(combinedQualifiers);
return new MemberExpr(BaseExpr, OpKind == tok::arrow, MemberDecl,
@@ -3484,7 +3492,11 @@
// Get the decl corresponding to this.
RecordDecl *RD = RC->getDecl();
- FieldDecl *MemberDecl = RD->getMember(OC.U.IdentInfo);
+ FieldDecl *MemberDecl = 0;
+ DeclContext::lookup_result Lookup = RD->lookup(Context, OC.U.IdentInfo);
+ if (Lookup.first != Lookup.second)
+ MemberDecl = dyn_cast<FieldDecl>(*Lookup.first);
+
if (!MemberDecl)
return Diag(BuiltinLoc, diag::err_typecheck_no_member)
<< OC.U.IdentInfo << SourceRange(OC.LocStart, OC.LocEnd);
@@ -3552,7 +3564,7 @@
BSI->TheScope = BlockScope;
BSI->TheDecl = BlockDecl::Create(Context, CurContext, CaretLoc);
- PushDeclContext(BSI->TheDecl);
+ PushDeclContext(BlockScope, BSI->TheDecl);
}
void Sema::ActOnBlockArguments(Declarator &ParamInfo) {
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Thu Dec 11 10:49:14 2008
@@ -412,9 +412,8 @@
DeclContext *Ctx, bool AllowMissing,
FunctionDecl *&Operator)
{
- IdentifierResolver::iterator I =
- IdResolver.begin(Name, Ctx, /*LookInParentCtx=*/false);
- if (I == IdResolver.end()) {
+ DeclContext::lookup_result Lookup = Ctx->lookup(Context, Name);
+ if (Lookup.first == Lookup.second) {
if (AllowMissing)
return false;
// FIXME: Bad location information.
@@ -423,7 +422,7 @@
}
OverloadCandidateSet Candidates;
- NamedDecl *Decl = *I;
+ NamedDecl *Decl = *Lookup.first;
// Even member operator new/delete are implicitly treated as static, so don't
// use AddMemberCandidate.
if (FunctionDecl *Fn = dyn_cast_or_null<FunctionDecl>(Decl))
Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Thu Dec 11 10:49:14 2008
@@ -15,6 +15,8 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/Diagnostic.h"
+#include <algorithm> // for std::count_if
+#include <functional> // for std::mem_fun
namespace clang {
@@ -39,10 +41,9 @@
int InitListChecker::numStructUnionElements(QualType DeclType) {
RecordDecl *structDecl = DeclType->getAsRecordType()->getDecl();
- int InitializableMembers = 0;
- for (int i = 0; i < structDecl->getNumMembers(); i++)
- if (structDecl->getMember(i)->getIdentifier())
- ++InitializableMembers;
+ int InitializableMembers
+ = std::count_if(structDecl->field_begin(), structDecl->field_end(),
+ std::mem_fun(&FieldDecl::getDeclName));
if (structDecl->isUnion())
return std::min(InitializableMembers, 1);
return InitializableMembers - structDecl->hasFlexibleArrayMember();
@@ -286,21 +287,28 @@
// If structDecl is a forward declaration, this loop won't do anything;
// That's okay, because an error should get printed out elsewhere. It
// might be worthwhile to skip over the rest of the initializer, though.
- int numMembers = DeclType->getAsRecordType()->getDecl()->getNumMembers() -
- structDecl->hasFlexibleArrayMember();
- for (int i = 0; i < numMembers; i++) {
+ RecordDecl *RD = DeclType->getAsRecordType()->getDecl();
+ for (RecordDecl::field_iterator Field = RD->field_begin(),
+ FieldEnd = RD->field_end();
+ Field != FieldEnd; ++Field) {
+ // If we've hit the flexible array member at the end, we're done.
+ if (Field->getType()->isIncompleteArrayType())
+ break;
+
// Don't attempt to go past the end of the init list
if (Index >= IList->getNumInits())
break;
- FieldDecl * curField = structDecl->getMember(i);
- if (!curField->getIdentifier()) {
+
+ if (!Field->getIdentifier()) {
// Don't initialize unnamed fields, e.g. "int : 20;"
continue;
}
- CheckSubElementType(IList, curField->getType(), Index);
+
+ CheckSubElementType(IList, Field->getType(), Index);
if (DeclType->isUnionType())
break;
}
+
// FIXME: Implement flexible array initialization GCC extension (it's a
// really messy extension to implement, unfortunately...the necessary
// information isn't actually even here!)
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Thu Dec 11 10:49:14 2008
@@ -1955,10 +1955,9 @@
// (13.3.1.1.1); otherwise, the set of member candidates is
// empty.
if (const RecordType *T1Rec = T1->getAsRecordType()) {
- IdentifierResolver::iterator I
- = IdResolver.begin(OpName, cast<CXXRecordType>(T1Rec)->getDecl(),
- /*LookInParentCtx=*/false);
- NamedDecl *MemberOps = (I == IdResolver.end())? 0 : *I;
+ DeclContext::lookup_const_result Lookup
+ = cast<CXXRecordType>(T1Rec)->getDecl()->lookup(Context, OpName);
+ NamedDecl *MemberOps = (Lookup.first == Lookup.second)? 0 : *Lookup.first;
if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(MemberOps))
AddMethodCandidate(Method, Args[0], Args+1, NumArgs - 1, CandidateSet,
/*SuppressUserConversions=*/false);
@@ -3118,11 +3117,10 @@
// ordinary lookup of the name operator() in the context of
// (E).operator().
OverloadCandidateSet CandidateSet;
- IdentifierResolver::iterator I
- = IdResolver.begin(Context.DeclarationNames.getCXXOperatorName(OO_Call),
- cast<CXXRecordType>(Record)->getDecl(),
- /*LookInParentCtx=*/false);
- NamedDecl *MemberOps = (I == IdResolver.end())? 0 : *I;
+ DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Call);
+ DeclContext::lookup_const_result Lookup
+ = cast<CXXRecordType>(Record)->getDecl()->lookup(Context, OpName);
+ NamedDecl *MemberOps = (Lookup.first == Lookup.second)? 0 : *Lookup.first;
if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(MemberOps))
AddMethodCandidate(Method, Object, Args, NumArgs, CandidateSet,
/*SuppressUserConversions=*/false);
@@ -3315,10 +3313,9 @@
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Arrow);
OverloadCandidateSet CandidateSet;
const RecordType *BaseRecord = Base->getType()->getAsRecordType();
- IdentifierResolver::iterator I
- = IdResolver.begin(OpName, cast<CXXRecordType>(BaseRecord)->getDecl(),
- /*LookInParentCtx=*/false);
- NamedDecl *MemberOps = (I == IdResolver.end())? 0 : *I;
+ DeclContext::lookup_const_result Lookup
+ = cast<CXXRecordType>(BaseRecord)->getDecl()->lookup(Context, OpName);
+ NamedDecl *MemberOps = (Lookup.first == Lookup.second)? 0 : *Lookup.first;
if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(MemberOps))
AddMethodCandidate(Method, Base, 0, 0, CandidateSet,
/*SuppressUserConversions=*/false);
Modified: cfe/trunk/test/SemaCXX/namespace.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/namespace.cpp?rev=60878&r1=60877&r2=60878&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/namespace.cpp (original)
+++ cfe/trunk/test/SemaCXX/namespace.cpp Thu Dec 11 10:49:14 2008
@@ -9,7 +9,6 @@
class A; // expected-error {{redefinition of 'A' as different kind of symbol}}
class B {}; // expected-note {{previous definition is here}}
-namespace B {} // expected-error {{redefinition of 'B' as different kind of symbol}}
void C(); // expected-note {{previous definition is here}}
namespace C {} // expected-error {{redefinition of 'C' as different kind of symbol}}
@@ -55,3 +54,5 @@
}
}
}
+
+namespace B {} // expected-error {{redefinition of 'B' as different kind of symbol}}
Added: cfe/trunk/test/SemaCXX/qualified-id-lookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/qualified-id-lookup.cpp?rev=60878&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/qualified-id-lookup.cpp (added)
+++ cfe/trunk/test/SemaCXX/qualified-id-lookup.cpp Thu Dec 11 10:49:14 2008
@@ -0,0 +1,53 @@
+// RUN: clang -fsyntax-only -verify %s
+
+namespace Ns {
+ int f(); // expected-note{{previous declaration is here}}
+}
+namespace Ns {
+ double f(); // expected-error{{functions that differ only in their return type cannot be overloaded}}
+}
+
+namespace Ns2 {
+ float f();
+}
+
+namespace Ns2 {
+ float f(int); // expected-note{{previous declaration is here}}
+}
+
+namespace Ns2 {
+ double f(int); // expected-error{{functions that differ only in their return type cannot be overloaded}}
+}
+
+namespace N {
+ int& f1();
+}
+
+namespace N {
+ struct f1 {
+ static int member;
+ };
+
+ void test_f1() {
+ int &i1 = f1();
+ }
+}
+
+namespace N {
+ float& f1(int);
+
+ struct f2 {
+ static int member;
+ };
+ void f2();
+}
+
+int i1 = N::f1::member;
+typedef struct N::f1 type1;
+int i2 = N::f2::member;
+typedef struct N::f2 type2;
+
+void test_f1(int i) {
+ int &v1 = N::f1();
+ float &v2 = N::f1(i);
+}
More information about the cfe-commits
mailing list