Change struct forward declarations and definitions to use unique RecordDecls, as opposed to creating a single RecordDecl and reusing it.
This change effects both RecordDecls and CXXRecordDecls, but does not effect EnumDecls (yet).
The motivation of this patch is as follows:
- Capture more source information, necessary for refactoring/rewriting clients.
- Pave the way to resolve ownership issues with RecordDecls with the forthcoming
addition of DeclGroups.
Current caveats:
- Until DeclGroups are in place, we will leak RecordDecls not explicitly
referenced by the AST. For example:
typedef struct { ... } x;
The RecordDecl for the struct will be leaked because the TypedefDecl doesn't
refer to it. This will be solved with DeclGroups.
- This patch also (temporarily) breaks CodeGen. More below.
High-level changes:
- As before, TagType still refers to a TagDecl, but it doesn't own it. When
a struct/union/class is first referenced, a RecordType and RecordDecl are
created for it, and the RecordType refers to that RecordDecl. Later, if
a new RecordDecl is created, the pointer to a RecordDecl in RecordType is
updated to point to the RecordDecl that defines the struct/union/class.
- TagDecl and RecordDecl now how a method 'getDefinition()' to return the
TagDecl*/RecordDecl* that refers to the TagDecl* that defines a particular
enum/struct/class/union. This is useful from going from a RecordDecl* that
defines a forward declaration to the RecordDecl* that provides the actual
definition. Note that this also works for EnumDecls, except that in this case
there is no distinction between forward declarations and definitions (yet).
- Clients should no longer assume that 'isDefinition()' returns true from a
RecordDecl if the corresponding struct/union/class has been defined.
isDefinition() only returns true if a particular RecordDecl is the defining
Decl. Use 'getDefinition()' instead to determine if a struct has been defined.
- The main changes to Sema happen in ActOnTag. To make the changes more
incremental, I split off the processing of enums and structs et al into two
code paths. Enums use the original code path (which is in ActOnTag) and
structs use the ActOnTagStruct. Eventually the two code paths will be merged,
but the idea was to preserve the original logic both for comparison and not to
change the logic for both enums and structs all at once.
- There is NO CHAINING of RecordDecls for the same RecordType. All RecordDecls
that correspond to the same type simply have a pointer to that type. If we
need to figure out what are all the RecordDecls for a given type we can build
a backmap.
- The diff in CXXRecordDecl.[cpp,h] is actually very small; it just mimics the
changes to RecordDecl. For some reason 'svn' marks the entire file as changed.
Why is CodeGen broken:
- Codegen assumes that there is an equivalence between RecordDecl* and
RecordType*. This was true before because we only created one RecordDecl* for
a given RecordType*, but it is no longer true. I believe this shouldn't be too
hard to change, but the patch was big enough as it is.
I have tested this patch on both the clang test suite, and by running the static analyzer over Postgresql and a large Apple-internal project (mix of Objective-C and C).
llvm-svn: 55839
2008-09-06 01:16:31 +08:00
|
|
|
//===--- DeclCXX.cpp - C++ Declaration AST Node Implementation ------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements the C++ related Decl classes.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "clang/AST/DeclCXX.h"
|
|
|
|
#include "clang/AST/ASTContext.h"
|
2008-11-13 07:21:09 +08:00
|
|
|
#include "clang/Basic/IdentifierTable.h"
|
2008-12-24 05:31:30 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
Change struct forward declarations and definitions to use unique RecordDecls, as opposed to creating a single RecordDecl and reusing it.
This change effects both RecordDecls and CXXRecordDecls, but does not effect EnumDecls (yet).
The motivation of this patch is as follows:
- Capture more source information, necessary for refactoring/rewriting clients.
- Pave the way to resolve ownership issues with RecordDecls with the forthcoming
addition of DeclGroups.
Current caveats:
- Until DeclGroups are in place, we will leak RecordDecls not explicitly
referenced by the AST. For example:
typedef struct { ... } x;
The RecordDecl for the struct will be leaked because the TypedefDecl doesn't
refer to it. This will be solved with DeclGroups.
- This patch also (temporarily) breaks CodeGen. More below.
High-level changes:
- As before, TagType still refers to a TagDecl, but it doesn't own it. When
a struct/union/class is first referenced, a RecordType and RecordDecl are
created for it, and the RecordType refers to that RecordDecl. Later, if
a new RecordDecl is created, the pointer to a RecordDecl in RecordType is
updated to point to the RecordDecl that defines the struct/union/class.
- TagDecl and RecordDecl now how a method 'getDefinition()' to return the
TagDecl*/RecordDecl* that refers to the TagDecl* that defines a particular
enum/struct/class/union. This is useful from going from a RecordDecl* that
defines a forward declaration to the RecordDecl* that provides the actual
definition. Note that this also works for EnumDecls, except that in this case
there is no distinction between forward declarations and definitions (yet).
- Clients should no longer assume that 'isDefinition()' returns true from a
RecordDecl if the corresponding struct/union/class has been defined.
isDefinition() only returns true if a particular RecordDecl is the defining
Decl. Use 'getDefinition()' instead to determine if a struct has been defined.
- The main changes to Sema happen in ActOnTag. To make the changes more
incremental, I split off the processing of enums and structs et al into two
code paths. Enums use the original code path (which is in ActOnTag) and
structs use the ActOnTagStruct. Eventually the two code paths will be merged,
but the idea was to preserve the original logic both for comparison and not to
change the logic for both enums and structs all at once.
- There is NO CHAINING of RecordDecls for the same RecordType. All RecordDecls
that correspond to the same type simply have a pointer to that type. If we
need to figure out what are all the RecordDecls for a given type we can build
a backmap.
- The diff in CXXRecordDecl.[cpp,h] is actually very small; it just mimics the
changes to RecordDecl. For some reason 'svn' marks the entire file as changed.
Why is CodeGen broken:
- Codegen assumes that there is an equivalence between RecordDecl* and
RecordType*. This was true before because we only created one RecordDecl* for
a given RecordType*, but it is no longer true. I believe this shouldn't be too
hard to change, but the patch was big enough as it is.
I have tested this patch on both the clang test suite, and by running the static analyzer over Postgresql and a large Apple-internal project (mix of Objective-C and C).
llvm-svn: 55839
2008-09-06 01:16:31 +08:00
|
|
|
using namespace clang;
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Decl Allocation/Deallocation Method Implementations
|
|
|
|
//===----------------------------------------------------------------------===//
|
2008-12-06 02:15:24 +08:00
|
|
|
|
Added ClassTemplateSpecializationDecl, which is a subclass of
CXXRecordDecl that is used to represent class template
specializations. These are canonical declarations that can refer to
either an actual class template specialization in the code, e.g.,
template<> class vector<bool> { };
or to a template instantiation. However, neither of these features is
actually implemented yet, so really we're just using (and uniqing) the
declarations to make sure that, e.g., A<int> is a different type from
A<float>. Note that we carefully distinguish between what the user
wrote in the source code (e.g., "A<FLOAT>") and the semantic entity it
represents (e.g., "A<float, int>"); the former is in the sugared Type,
the latter is an actual Decl.
llvm-svn: 64716
2009-02-17 09:05:43 +08:00
|
|
|
CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
|
2008-11-13 07:21:09 +08:00
|
|
|
SourceLocation L, IdentifierInfo *Id)
|
Added ClassTemplateSpecializationDecl, which is a subclass of
CXXRecordDecl that is used to represent class template
specializations. These are canonical declarations that can refer to
either an actual class template specialization in the code, e.g.,
template<> class vector<bool> { };
or to a template instantiation. However, neither of these features is
actually implemented yet, so really we're just using (and uniqing) the
declarations to make sure that, e.g., A<int> is a different type from
A<float>. Note that we carefully distinguish between what the user
wrote in the source code (e.g., "A<FLOAT>") and the semantic entity it
represents (e.g., "A<float, int>"); the former is in the sugared Type,
the latter is an actual Decl.
llvm-svn: 64716
2009-02-17 09:05:43 +08:00
|
|
|
: RecordDecl(K, TK, DC, L, Id),
|
2008-11-13 07:21:09 +08:00
|
|
|
UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
|
2009-01-06 04:52:13 +08:00
|
|
|
UserDeclaredCopyAssignment(false), UserDeclaredDestructor(false),
|
|
|
|
Aggregate(true), PlainOldData(true), Polymorphic(false), Bases(0),
|
|
|
|
NumBases(0), Conversions(DC, DeclarationName()) { }
|
2008-11-13 07:21:09 +08:00
|
|
|
|
Change struct forward declarations and definitions to use unique RecordDecls, as opposed to creating a single RecordDecl and reusing it.
This change effects both RecordDecls and CXXRecordDecls, but does not effect EnumDecls (yet).
The motivation of this patch is as follows:
- Capture more source information, necessary for refactoring/rewriting clients.
- Pave the way to resolve ownership issues with RecordDecls with the forthcoming
addition of DeclGroups.
Current caveats:
- Until DeclGroups are in place, we will leak RecordDecls not explicitly
referenced by the AST. For example:
typedef struct { ... } x;
The RecordDecl for the struct will be leaked because the TypedefDecl doesn't
refer to it. This will be solved with DeclGroups.
- This patch also (temporarily) breaks CodeGen. More below.
High-level changes:
- As before, TagType still refers to a TagDecl, but it doesn't own it. When
a struct/union/class is first referenced, a RecordType and RecordDecl are
created for it, and the RecordType refers to that RecordDecl. Later, if
a new RecordDecl is created, the pointer to a RecordDecl in RecordType is
updated to point to the RecordDecl that defines the struct/union/class.
- TagDecl and RecordDecl now how a method 'getDefinition()' to return the
TagDecl*/RecordDecl* that refers to the TagDecl* that defines a particular
enum/struct/class/union. This is useful from going from a RecordDecl* that
defines a forward declaration to the RecordDecl* that provides the actual
definition. Note that this also works for EnumDecls, except that in this case
there is no distinction between forward declarations and definitions (yet).
- Clients should no longer assume that 'isDefinition()' returns true from a
RecordDecl if the corresponding struct/union/class has been defined.
isDefinition() only returns true if a particular RecordDecl is the defining
Decl. Use 'getDefinition()' instead to determine if a struct has been defined.
- The main changes to Sema happen in ActOnTag. To make the changes more
incremental, I split off the processing of enums and structs et al into two
code paths. Enums use the original code path (which is in ActOnTag) and
structs use the ActOnTagStruct. Eventually the two code paths will be merged,
but the idea was to preserve the original logic both for comparison and not to
change the logic for both enums and structs all at once.
- There is NO CHAINING of RecordDecls for the same RecordType. All RecordDecls
that correspond to the same type simply have a pointer to that type. If we
need to figure out what are all the RecordDecls for a given type we can build
a backmap.
- The diff in CXXRecordDecl.[cpp,h] is actually very small; it just mimics the
changes to RecordDecl. For some reason 'svn' marks the entire file as changed.
Why is CodeGen broken:
- Codegen assumes that there is an equivalence between RecordDecl* and
RecordType*. This was true before because we only created one RecordDecl* for
a given RecordType*, but it is no longer true. I believe this shouldn't be too
hard to change, but the patch was big enough as it is.
I have tested this patch on both the clang test suite, and by running the static analyzer over Postgresql and a large Apple-internal project (mix of Objective-C and C).
llvm-svn: 55839
2008-09-06 01:16:31 +08:00
|
|
|
CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
|
|
|
|
SourceLocation L, IdentifierInfo *Id,
|
|
|
|
CXXRecordDecl* PrevDecl) {
|
Added ClassTemplateSpecializationDecl, which is a subclass of
CXXRecordDecl that is used to represent class template
specializations. These are canonical declarations that can refer to
either an actual class template specialization in the code, e.g.,
template<> class vector<bool> { };
or to a template instantiation. However, neither of these features is
actually implemented yet, so really we're just using (and uniqing) the
declarations to make sure that, e.g., A<int> is a different type from
A<float>. Note that we carefully distinguish between what the user
wrote in the source code (e.g., "A<FLOAT>") and the semantic entity it
represents (e.g., "A<float, int>"); the former is in the sugared Type,
the latter is an actual Decl.
llvm-svn: 64716
2009-02-17 09:05:43 +08:00
|
|
|
CXXRecordDecl* R = new (C) CXXRecordDecl(CXXRecord, TK, DC, L, Id);
|
Change struct forward declarations and definitions to use unique RecordDecls, as opposed to creating a single RecordDecl and reusing it.
This change effects both RecordDecls and CXXRecordDecls, but does not effect EnumDecls (yet).
The motivation of this patch is as follows:
- Capture more source information, necessary for refactoring/rewriting clients.
- Pave the way to resolve ownership issues with RecordDecls with the forthcoming
addition of DeclGroups.
Current caveats:
- Until DeclGroups are in place, we will leak RecordDecls not explicitly
referenced by the AST. For example:
typedef struct { ... } x;
The RecordDecl for the struct will be leaked because the TypedefDecl doesn't
refer to it. This will be solved with DeclGroups.
- This patch also (temporarily) breaks CodeGen. More below.
High-level changes:
- As before, TagType still refers to a TagDecl, but it doesn't own it. When
a struct/union/class is first referenced, a RecordType and RecordDecl are
created for it, and the RecordType refers to that RecordDecl. Later, if
a new RecordDecl is created, the pointer to a RecordDecl in RecordType is
updated to point to the RecordDecl that defines the struct/union/class.
- TagDecl and RecordDecl now how a method 'getDefinition()' to return the
TagDecl*/RecordDecl* that refers to the TagDecl* that defines a particular
enum/struct/class/union. This is useful from going from a RecordDecl* that
defines a forward declaration to the RecordDecl* that provides the actual
definition. Note that this also works for EnumDecls, except that in this case
there is no distinction between forward declarations and definitions (yet).
- Clients should no longer assume that 'isDefinition()' returns true from a
RecordDecl if the corresponding struct/union/class has been defined.
isDefinition() only returns true if a particular RecordDecl is the defining
Decl. Use 'getDefinition()' instead to determine if a struct has been defined.
- The main changes to Sema happen in ActOnTag. To make the changes more
incremental, I split off the processing of enums and structs et al into two
code paths. Enums use the original code path (which is in ActOnTag) and
structs use the ActOnTagStruct. Eventually the two code paths will be merged,
but the idea was to preserve the original logic both for comparison and not to
change the logic for both enums and structs all at once.
- There is NO CHAINING of RecordDecls for the same RecordType. All RecordDecls
that correspond to the same type simply have a pointer to that type. If we
need to figure out what are all the RecordDecls for a given type we can build
a backmap.
- The diff in CXXRecordDecl.[cpp,h] is actually very small; it just mimics the
changes to RecordDecl. For some reason 'svn' marks the entire file as changed.
Why is CodeGen broken:
- Codegen assumes that there is an equivalence between RecordDecl* and
RecordType*. This was true before because we only created one RecordDecl* for
a given RecordType*, but it is no longer true. I believe this shouldn't be too
hard to change, but the patch was big enough as it is.
I have tested this patch on both the clang test suite, and by running the static analyzer over Postgresql and a large Apple-internal project (mix of Objective-C and C).
llvm-svn: 55839
2008-09-06 01:16:31 +08:00
|
|
|
C.getTypeDeclType(R, PrevDecl);
|
|
|
|
return R;
|
|
|
|
}
|
|
|
|
|
2008-10-23 01:49:05 +08:00
|
|
|
CXXRecordDecl::~CXXRecordDecl() {
|
|
|
|
delete [] Bases;
|
|
|
|
}
|
|
|
|
|
2008-10-24 02:13:27 +08:00
|
|
|
void
|
|
|
|
CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
|
|
|
|
unsigned NumBases) {
|
2008-11-06 00:20:31 +08:00
|
|
|
// C++ [dcl.init.aggr]p1:
|
|
|
|
// An aggregate is an array or a class (clause 9) with [...]
|
|
|
|
// no base classes [...].
|
|
|
|
Aggregate = false;
|
|
|
|
|
2008-10-24 02:13:27 +08:00
|
|
|
if (this->Bases)
|
|
|
|
delete [] this->Bases;
|
|
|
|
|
|
|
|
this->Bases = new CXXBaseSpecifier[NumBases];
|
|
|
|
this->NumBases = NumBases;
|
|
|
|
for (unsigned i = 0; i < NumBases; ++i)
|
|
|
|
this->Bases[i] = *Bases[i];
|
|
|
|
}
|
|
|
|
|
2008-11-04 01:51:48 +08:00
|
|
|
bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const {
|
2009-01-06 04:52:13 +08:00
|
|
|
QualType ClassType
|
|
|
|
= Context.getTypeDeclType(const_cast<CXXRecordDecl*>(this));
|
2008-12-16 05:24:18 +08:00
|
|
|
DeclarationName ConstructorName
|
|
|
|
= Context.DeclarationNames.getCXXConstructorName(
|
|
|
|
Context.getCanonicalType(ClassType));
|
|
|
|
unsigned TypeQuals;
|
2008-12-24 05:31:30 +08:00
|
|
|
DeclContext::lookup_const_iterator Con, ConEnd;
|
2009-01-09 01:28:14 +08:00
|
|
|
for (llvm::tie(Con, ConEnd) = this->lookup(ConstructorName);
|
2008-12-24 05:31:30 +08:00
|
|
|
Con != ConEnd; ++Con) {
|
2008-11-04 01:51:48 +08:00
|
|
|
if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context, TypeQuals) &&
|
2008-12-17 04:06:41 +08:00
|
|
|
(TypeQuals & QualType::Const) != 0)
|
2008-11-04 01:51:48 +08:00
|
|
|
return true;
|
|
|
|
}
|
2008-12-24 05:31:30 +08:00
|
|
|
|
2008-11-04 01:51:48 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-01-06 04:52:13 +08:00
|
|
|
bool CXXRecordDecl::hasConstCopyAssignment(ASTContext &Context) const {
|
|
|
|
QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(
|
|
|
|
const_cast<CXXRecordDecl*>(this)));
|
|
|
|
DeclarationName OpName =Context.DeclarationNames.getCXXOperatorName(OO_Equal);
|
|
|
|
|
|
|
|
DeclContext::lookup_const_iterator Op, OpEnd;
|
2009-01-09 01:28:14 +08:00
|
|
|
for (llvm::tie(Op, OpEnd) = this->lookup(OpName);
|
2009-01-06 04:52:13 +08:00
|
|
|
Op != OpEnd; ++Op) {
|
|
|
|
// C++ [class.copy]p9:
|
|
|
|
// A user-declared copy assignment operator is a non-static non-template
|
|
|
|
// member function of class X with exactly one parameter of type X, X&,
|
|
|
|
// const X&, volatile X& or const volatile X&.
|
|
|
|
const CXXMethodDecl* Method = cast<CXXMethodDecl>(*Op);
|
|
|
|
if (Method->isStatic())
|
|
|
|
continue;
|
|
|
|
// TODO: Skip templates? Or is this implicitly done due to parameter types?
|
2009-02-27 07:50:07 +08:00
|
|
|
const FunctionProtoType *FnType =
|
|
|
|
Method->getType()->getAsFunctionProtoType();
|
2009-01-06 04:52:13 +08:00
|
|
|
assert(FnType && "Overloaded operator has no prototype.");
|
|
|
|
// Don't assert on this; an invalid decl might have been left in the AST.
|
|
|
|
if (FnType->getNumArgs() != 1 || FnType->isVariadic())
|
|
|
|
continue;
|
|
|
|
bool AcceptsConst = true;
|
|
|
|
QualType ArgType = FnType->getArgType(0);
|
|
|
|
if (const ReferenceType *Ref = ArgType->getAsReferenceType()) {
|
|
|
|
ArgType = Ref->getPointeeType();
|
|
|
|
// Is it a non-const reference?
|
|
|
|
if (!ArgType.isConstQualified())
|
|
|
|
AcceptsConst = false;
|
|
|
|
}
|
|
|
|
if (Context.getCanonicalType(ArgType).getUnqualifiedType() != ClassType)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// We have a single argument of type cv X or cv X&, i.e. we've found the
|
|
|
|
// copy assignment operator. Return whether it accepts const arguments.
|
|
|
|
return AcceptsConst;
|
|
|
|
}
|
|
|
|
assert(isInvalidDecl() &&
|
|
|
|
"No copy assignment operator declared in valid code.");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-12-16 05:24:18 +08:00
|
|
|
CXXRecordDecl::addedConstructor(ASTContext &Context,
|
|
|
|
CXXConstructorDecl *ConDecl) {
|
2009-01-08 03:46:03 +08:00
|
|
|
if (!ConDecl->isImplicit()) {
|
2008-11-01 04:25:05 +08:00
|
|
|
// Note that we have a user-declared constructor.
|
|
|
|
UserDeclaredConstructor = true;
|
|
|
|
|
2008-11-06 00:20:31 +08:00
|
|
|
// C++ [dcl.init.aggr]p1:
|
|
|
|
// An aggregate is an array or a class (clause 9) with no
|
|
|
|
// user-declared constructors (12.1) [...].
|
|
|
|
Aggregate = false;
|
|
|
|
|
2009-01-06 04:52:13 +08:00
|
|
|
// C++ [class]p4:
|
|
|
|
// A POD-struct is an aggregate class [...]
|
|
|
|
PlainOldData = false;
|
|
|
|
|
2008-11-01 04:25:05 +08:00
|
|
|
// Note when we have a user-declared copy constructor, which will
|
|
|
|
// suppress the implicit declaration of a copy constructor.
|
|
|
|
if (ConDecl->isCopyConstructor(Context))
|
|
|
|
UserDeclaredCopyConstructor = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-06 04:52:13 +08:00
|
|
|
void CXXRecordDecl::addedAssignmentOperator(ASTContext &Context,
|
|
|
|
CXXMethodDecl *OpDecl) {
|
|
|
|
// We're interested specifically in copy assignment operators.
|
|
|
|
// Unlike addedConstructor, this method is not called for implicit
|
|
|
|
// declarations.
|
2009-02-27 07:50:07 +08:00
|
|
|
const FunctionProtoType *FnType = OpDecl->getType()->getAsFunctionProtoType();
|
2009-01-06 04:52:13 +08:00
|
|
|
assert(FnType && "Overloaded operator has no proto function type.");
|
|
|
|
assert(FnType->getNumArgs() == 1 && !FnType->isVariadic());
|
|
|
|
QualType ArgType = FnType->getArgType(0);
|
|
|
|
if (const ReferenceType *Ref = ArgType->getAsReferenceType())
|
|
|
|
ArgType = Ref->getPointeeType();
|
|
|
|
|
|
|
|
ArgType = ArgType.getUnqualifiedType();
|
|
|
|
QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(
|
|
|
|
const_cast<CXXRecordDecl*>(this)));
|
|
|
|
|
|
|
|
if (ClassType != Context.getCanonicalType(ArgType))
|
|
|
|
return;
|
|
|
|
|
|
|
|
// This is a copy assignment operator.
|
|
|
|
// Suppress the implicit declaration of a copy constructor.
|
|
|
|
UserDeclaredCopyAssignment = true;
|
|
|
|
|
|
|
|
// C++ [class]p4:
|
|
|
|
// A POD-struct is an aggregate class that [...] has no user-defined copy
|
|
|
|
// assignment operator [...].
|
|
|
|
PlainOldData = false;
|
|
|
|
}
|
|
|
|
|
2008-11-08 04:08:42 +08:00
|
|
|
void CXXRecordDecl::addConversionFunction(ASTContext &Context,
|
|
|
|
CXXConversionDecl *ConvDecl) {
|
|
|
|
Conversions.addOverload(ConvDecl);
|
|
|
|
}
|
|
|
|
|
Change struct forward declarations and definitions to use unique RecordDecls, as opposed to creating a single RecordDecl and reusing it.
This change effects both RecordDecls and CXXRecordDecls, but does not effect EnumDecls (yet).
The motivation of this patch is as follows:
- Capture more source information, necessary for refactoring/rewriting clients.
- Pave the way to resolve ownership issues with RecordDecls with the forthcoming
addition of DeclGroups.
Current caveats:
- Until DeclGroups are in place, we will leak RecordDecls not explicitly
referenced by the AST. For example:
typedef struct { ... } x;
The RecordDecl for the struct will be leaked because the TypedefDecl doesn't
refer to it. This will be solved with DeclGroups.
- This patch also (temporarily) breaks CodeGen. More below.
High-level changes:
- As before, TagType still refers to a TagDecl, but it doesn't own it. When
a struct/union/class is first referenced, a RecordType and RecordDecl are
created for it, and the RecordType refers to that RecordDecl. Later, if
a new RecordDecl is created, the pointer to a RecordDecl in RecordType is
updated to point to the RecordDecl that defines the struct/union/class.
- TagDecl and RecordDecl now how a method 'getDefinition()' to return the
TagDecl*/RecordDecl* that refers to the TagDecl* that defines a particular
enum/struct/class/union. This is useful from going from a RecordDecl* that
defines a forward declaration to the RecordDecl* that provides the actual
definition. Note that this also works for EnumDecls, except that in this case
there is no distinction between forward declarations and definitions (yet).
- Clients should no longer assume that 'isDefinition()' returns true from a
RecordDecl if the corresponding struct/union/class has been defined.
isDefinition() only returns true if a particular RecordDecl is the defining
Decl. Use 'getDefinition()' instead to determine if a struct has been defined.
- The main changes to Sema happen in ActOnTag. To make the changes more
incremental, I split off the processing of enums and structs et al into two
code paths. Enums use the original code path (which is in ActOnTag) and
structs use the ActOnTagStruct. Eventually the two code paths will be merged,
but the idea was to preserve the original logic both for comparison and not to
change the logic for both enums and structs all at once.
- There is NO CHAINING of RecordDecls for the same RecordType. All RecordDecls
that correspond to the same type simply have a pointer to that type. If we
need to figure out what are all the RecordDecls for a given type we can build
a backmap.
- The diff in CXXRecordDecl.[cpp,h] is actually very small; it just mimics the
changes to RecordDecl. For some reason 'svn' marks the entire file as changed.
Why is CodeGen broken:
- Codegen assumes that there is an equivalence between RecordDecl* and
RecordType*. This was true before because we only created one RecordDecl* for
a given RecordType*, but it is no longer true. I believe this shouldn't be too
hard to change, but the patch was big enough as it is.
I have tested this patch on both the clang test suite, and by running the static analyzer over Postgresql and a large Apple-internal project (mix of Objective-C and C).
llvm-svn: 55839
2008-09-06 01:16:31 +08:00
|
|
|
CXXMethodDecl *
|
|
|
|
CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
|
2008-11-18 06:58:34 +08:00
|
|
|
SourceLocation L, DeclarationName N,
|
2009-01-20 09:17:11 +08:00
|
|
|
QualType T, bool isStatic, bool isInline) {
|
2009-01-28 05:25:57 +08:00
|
|
|
return new (C) CXXMethodDecl(CXXMethod, RD, L, N, T, isStatic, isInline);
|
Change struct forward declarations and definitions to use unique RecordDecls, as opposed to creating a single RecordDecl and reusing it.
This change effects both RecordDecls and CXXRecordDecls, but does not effect EnumDecls (yet).
The motivation of this patch is as follows:
- Capture more source information, necessary for refactoring/rewriting clients.
- Pave the way to resolve ownership issues with RecordDecls with the forthcoming
addition of DeclGroups.
Current caveats:
- Until DeclGroups are in place, we will leak RecordDecls not explicitly
referenced by the AST. For example:
typedef struct { ... } x;
The RecordDecl for the struct will be leaked because the TypedefDecl doesn't
refer to it. This will be solved with DeclGroups.
- This patch also (temporarily) breaks CodeGen. More below.
High-level changes:
- As before, TagType still refers to a TagDecl, but it doesn't own it. When
a struct/union/class is first referenced, a RecordType and RecordDecl are
created for it, and the RecordType refers to that RecordDecl. Later, if
a new RecordDecl is created, the pointer to a RecordDecl in RecordType is
updated to point to the RecordDecl that defines the struct/union/class.
- TagDecl and RecordDecl now how a method 'getDefinition()' to return the
TagDecl*/RecordDecl* that refers to the TagDecl* that defines a particular
enum/struct/class/union. This is useful from going from a RecordDecl* that
defines a forward declaration to the RecordDecl* that provides the actual
definition. Note that this also works for EnumDecls, except that in this case
there is no distinction between forward declarations and definitions (yet).
- Clients should no longer assume that 'isDefinition()' returns true from a
RecordDecl if the corresponding struct/union/class has been defined.
isDefinition() only returns true if a particular RecordDecl is the defining
Decl. Use 'getDefinition()' instead to determine if a struct has been defined.
- The main changes to Sema happen in ActOnTag. To make the changes more
incremental, I split off the processing of enums and structs et al into two
code paths. Enums use the original code path (which is in ActOnTag) and
structs use the ActOnTagStruct. Eventually the two code paths will be merged,
but the idea was to preserve the original logic both for comparison and not to
change the logic for both enums and structs all at once.
- There is NO CHAINING of RecordDecls for the same RecordType. All RecordDecls
that correspond to the same type simply have a pointer to that type. If we
need to figure out what are all the RecordDecls for a given type we can build
a backmap.
- The diff in CXXRecordDecl.[cpp,h] is actually very small; it just mimics the
changes to RecordDecl. For some reason 'svn' marks the entire file as changed.
Why is CodeGen broken:
- Codegen assumes that there is an equivalence between RecordDecl* and
RecordType*. This was true before because we only created one RecordDecl* for
a given RecordType*, but it is no longer true. I believe this shouldn't be too
hard to change, but the patch was big enough as it is.
I have tested this patch on both the clang test suite, and by running the static analyzer over Postgresql and a large Apple-internal project (mix of Objective-C and C).
llvm-svn: 55839
2008-09-06 01:16:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
QualType CXXMethodDecl::getThisType(ASTContext &C) const {
|
2008-10-25 06:28:18 +08:00
|
|
|
// C++ 9.3.2p1: The type of this in a member function of a class X is X*.
|
|
|
|
// If the member function is declared const, the type of this is const X*,
|
|
|
|
// if the member function is declared volatile, the type of this is
|
|
|
|
// volatile X*, and if the member function is declared const volatile,
|
|
|
|
// the type of this is const volatile X*.
|
|
|
|
|
Change struct forward declarations and definitions to use unique RecordDecls, as opposed to creating a single RecordDecl and reusing it.
This change effects both RecordDecls and CXXRecordDecls, but does not effect EnumDecls (yet).
The motivation of this patch is as follows:
- Capture more source information, necessary for refactoring/rewriting clients.
- Pave the way to resolve ownership issues with RecordDecls with the forthcoming
addition of DeclGroups.
Current caveats:
- Until DeclGroups are in place, we will leak RecordDecls not explicitly
referenced by the AST. For example:
typedef struct { ... } x;
The RecordDecl for the struct will be leaked because the TypedefDecl doesn't
refer to it. This will be solved with DeclGroups.
- This patch also (temporarily) breaks CodeGen. More below.
High-level changes:
- As before, TagType still refers to a TagDecl, but it doesn't own it. When
a struct/union/class is first referenced, a RecordType and RecordDecl are
created for it, and the RecordType refers to that RecordDecl. Later, if
a new RecordDecl is created, the pointer to a RecordDecl in RecordType is
updated to point to the RecordDecl that defines the struct/union/class.
- TagDecl and RecordDecl now how a method 'getDefinition()' to return the
TagDecl*/RecordDecl* that refers to the TagDecl* that defines a particular
enum/struct/class/union. This is useful from going from a RecordDecl* that
defines a forward declaration to the RecordDecl* that provides the actual
definition. Note that this also works for EnumDecls, except that in this case
there is no distinction between forward declarations and definitions (yet).
- Clients should no longer assume that 'isDefinition()' returns true from a
RecordDecl if the corresponding struct/union/class has been defined.
isDefinition() only returns true if a particular RecordDecl is the defining
Decl. Use 'getDefinition()' instead to determine if a struct has been defined.
- The main changes to Sema happen in ActOnTag. To make the changes more
incremental, I split off the processing of enums and structs et al into two
code paths. Enums use the original code path (which is in ActOnTag) and
structs use the ActOnTagStruct. Eventually the two code paths will be merged,
but the idea was to preserve the original logic both for comparison and not to
change the logic for both enums and structs all at once.
- There is NO CHAINING of RecordDecls for the same RecordType. All RecordDecls
that correspond to the same type simply have a pointer to that type. If we
need to figure out what are all the RecordDecls for a given type we can build
a backmap.
- The diff in CXXRecordDecl.[cpp,h] is actually very small; it just mimics the
changes to RecordDecl. For some reason 'svn' marks the entire file as changed.
Why is CodeGen broken:
- Codegen assumes that there is an equivalence between RecordDecl* and
RecordType*. This was true before because we only created one RecordDecl* for
a given RecordType*, but it is no longer true. I believe this shouldn't be too
hard to change, but the patch was big enough as it is.
I have tested this patch on both the clang test suite, and by running the static analyzer over Postgresql and a large Apple-internal project (mix of Objective-C and C).
llvm-svn: 55839
2008-09-06 01:16:31 +08:00
|
|
|
assert(isInstance() && "No 'this' for static methods!");
|
2008-11-01 04:25:05 +08:00
|
|
|
QualType ClassTy = C.getTagDeclType(const_cast<CXXRecordDecl*>(getParent()));
|
2008-10-25 05:46:40 +08:00
|
|
|
ClassTy = ClassTy.getWithAdditionalQualifiers(getTypeQualifiers());
|
|
|
|
return C.getPointerType(ClassTy).withConst();
|
Change struct forward declarations and definitions to use unique RecordDecls, as opposed to creating a single RecordDecl and reusing it.
This change effects both RecordDecls and CXXRecordDecls, but does not effect EnumDecls (yet).
The motivation of this patch is as follows:
- Capture more source information, necessary for refactoring/rewriting clients.
- Pave the way to resolve ownership issues with RecordDecls with the forthcoming
addition of DeclGroups.
Current caveats:
- Until DeclGroups are in place, we will leak RecordDecls not explicitly
referenced by the AST. For example:
typedef struct { ... } x;
The RecordDecl for the struct will be leaked because the TypedefDecl doesn't
refer to it. This will be solved with DeclGroups.
- This patch also (temporarily) breaks CodeGen. More below.
High-level changes:
- As before, TagType still refers to a TagDecl, but it doesn't own it. When
a struct/union/class is first referenced, a RecordType and RecordDecl are
created for it, and the RecordType refers to that RecordDecl. Later, if
a new RecordDecl is created, the pointer to a RecordDecl in RecordType is
updated to point to the RecordDecl that defines the struct/union/class.
- TagDecl and RecordDecl now how a method 'getDefinition()' to return the
TagDecl*/RecordDecl* that refers to the TagDecl* that defines a particular
enum/struct/class/union. This is useful from going from a RecordDecl* that
defines a forward declaration to the RecordDecl* that provides the actual
definition. Note that this also works for EnumDecls, except that in this case
there is no distinction between forward declarations and definitions (yet).
- Clients should no longer assume that 'isDefinition()' returns true from a
RecordDecl if the corresponding struct/union/class has been defined.
isDefinition() only returns true if a particular RecordDecl is the defining
Decl. Use 'getDefinition()' instead to determine if a struct has been defined.
- The main changes to Sema happen in ActOnTag. To make the changes more
incremental, I split off the processing of enums and structs et al into two
code paths. Enums use the original code path (which is in ActOnTag) and
structs use the ActOnTagStruct. Eventually the two code paths will be merged,
but the idea was to preserve the original logic both for comparison and not to
change the logic for both enums and structs all at once.
- There is NO CHAINING of RecordDecls for the same RecordType. All RecordDecls
that correspond to the same type simply have a pointer to that type. If we
need to figure out what are all the RecordDecls for a given type we can build
a backmap.
- The diff in CXXRecordDecl.[cpp,h] is actually very small; it just mimics the
changes to RecordDecl. For some reason 'svn' marks the entire file as changed.
Why is CodeGen broken:
- Codegen assumes that there is an equivalence between RecordDecl* and
RecordType*. This was true before because we only created one RecordDecl* for
a given RecordType*, but it is no longer true. I believe this shouldn't be too
hard to change, but the patch was big enough as it is.
I have tested this patch on both the clang test suite, and by running the static analyzer over Postgresql and a large Apple-internal project (mix of Objective-C and C).
llvm-svn: 55839
2008-09-06 01:16:31 +08:00
|
|
|
}
|
|
|
|
|
2008-11-05 12:29:56 +08:00
|
|
|
CXXBaseOrMemberInitializer::
|
|
|
|
CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs)
|
|
|
|
: Args(0), NumArgs(0) {
|
|
|
|
BaseOrMember = reinterpret_cast<uintptr_t>(BaseType.getTypePtr());
|
|
|
|
assert((BaseOrMember & 0x01) == 0 && "Invalid base class type pointer");
|
|
|
|
BaseOrMember |= 0x01;
|
|
|
|
|
|
|
|
if (NumArgs > 0) {
|
|
|
|
this->NumArgs = NumArgs;
|
|
|
|
this->Args = new Expr*[NumArgs];
|
|
|
|
for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
|
|
|
|
this->Args[Idx] = Args[Idx];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CXXBaseOrMemberInitializer::
|
2008-12-12 00:49:14 +08:00
|
|
|
CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs)
|
2008-11-05 12:29:56 +08:00
|
|
|
: Args(0), NumArgs(0) {
|
|
|
|
BaseOrMember = reinterpret_cast<uintptr_t>(Member);
|
|
|
|
assert((BaseOrMember & 0x01) == 0 && "Invalid member pointer");
|
|
|
|
|
|
|
|
if (NumArgs > 0) {
|
|
|
|
this->NumArgs = NumArgs;
|
|
|
|
this->Args = new Expr*[NumArgs];
|
|
|
|
for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
|
|
|
|
this->Args[Idx] = Args[Idx];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CXXBaseOrMemberInitializer::~CXXBaseOrMemberInitializer() {
|
|
|
|
delete [] Args;
|
|
|
|
}
|
|
|
|
|
2008-10-31 17:07:45 +08:00
|
|
|
CXXConstructorDecl *
|
|
|
|
CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
|
2008-11-17 22:58:09 +08:00
|
|
|
SourceLocation L, DeclarationName N,
|
2008-10-31 17:07:45 +08:00
|
|
|
QualType T, bool isExplicit,
|
|
|
|
bool isInline, bool isImplicitlyDeclared) {
|
2008-11-17 22:58:09 +08:00
|
|
|
assert(N.getNameKind() == DeclarationName::CXXConstructorName &&
|
|
|
|
"Name must refer to a constructor");
|
2009-01-28 05:25:57 +08:00
|
|
|
return new (C) CXXConstructorDecl(RD, L, N, T, isExplicit, isInline,
|
2008-10-31 17:07:45 +08:00
|
|
|
isImplicitlyDeclared);
|
|
|
|
}
|
|
|
|
|
2008-11-01 04:25:05 +08:00
|
|
|
bool CXXConstructorDecl::isDefaultConstructor() const {
|
|
|
|
// C++ [class.ctor]p5:
|
2008-11-06 00:20:31 +08:00
|
|
|
// A default constructor for a class X is a constructor of class
|
|
|
|
// X that can be called without an argument.
|
2008-11-01 04:25:05 +08:00
|
|
|
return (getNumParams() == 0) ||
|
2008-11-05 23:29:30 +08:00
|
|
|
(getNumParams() > 0 && getParamDecl(0)->getDefaultArg() != 0);
|
2008-11-01 04:25:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
CXXConstructorDecl::isCopyConstructor(ASTContext &Context,
|
|
|
|
unsigned &TypeQuals) const {
|
|
|
|
// C++ [class.copy]p2:
|
2008-11-06 00:20:31 +08:00
|
|
|
// A non-template constructor for class X is a copy constructor
|
|
|
|
// if its first parameter is of type X&, const X&, volatile X& or
|
|
|
|
// const volatile X&, and either there are no other parameters
|
|
|
|
// or else all other parameters have default arguments (8.3.6).
|
2008-11-01 04:25:05 +08:00
|
|
|
if ((getNumParams() < 1) ||
|
|
|
|
(getNumParams() > 1 && getParamDecl(1)->getDefaultArg() == 0))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const ParmVarDecl *Param = getParamDecl(0);
|
|
|
|
|
|
|
|
// Do we have a reference type?
|
|
|
|
const ReferenceType *ParamRefType = Param->getType()->getAsReferenceType();
|
|
|
|
if (!ParamRefType)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Is it a reference to our class type?
|
|
|
|
QualType PointeeType
|
|
|
|
= Context.getCanonicalType(ParamRefType->getPointeeType());
|
|
|
|
QualType ClassTy
|
|
|
|
= Context.getTagDeclType(const_cast<CXXRecordDecl*>(getParent()));
|
|
|
|
if (PointeeType.getUnqualifiedType() != ClassTy)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// We have a copy constructor.
|
|
|
|
TypeQuals = PointeeType.getCVRQualifiers();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2008-11-01 00:23:19 +08:00
|
|
|
bool CXXConstructorDecl::isConvertingConstructor() const {
|
|
|
|
// C++ [class.conv.ctor]p1:
|
|
|
|
// A constructor declared without the function-specifier explicit
|
|
|
|
// that can be called with a single parameter specifies a
|
|
|
|
// conversion from the type of its first parameter to the type of
|
|
|
|
// its class. Such a constructor is called a converting
|
|
|
|
// constructor.
|
|
|
|
if (isExplicit())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return (getNumParams() == 0 &&
|
2009-02-27 07:50:07 +08:00
|
|
|
getType()->getAsFunctionProtoType()->isVariadic()) ||
|
2008-11-01 00:23:19 +08:00
|
|
|
(getNumParams() == 1) ||
|
|
|
|
(getNumParams() > 1 && getParamDecl(1)->getDefaultArg() != 0);
|
|
|
|
}
|
2008-10-31 17:07:45 +08:00
|
|
|
|
2008-11-06 04:51:48 +08:00
|
|
|
CXXDestructorDecl *
|
|
|
|
CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
|
2008-11-17 22:58:09 +08:00
|
|
|
SourceLocation L, DeclarationName N,
|
2008-11-06 04:51:48 +08:00
|
|
|
QualType T, bool isInline,
|
|
|
|
bool isImplicitlyDeclared) {
|
2008-11-17 22:58:09 +08:00
|
|
|
assert(N.getNameKind() == DeclarationName::CXXDestructorName &&
|
|
|
|
"Name must refer to a destructor");
|
2009-01-28 05:25:57 +08:00
|
|
|
return new (C) CXXDestructorDecl(RD, L, N, T, isInline,
|
|
|
|
isImplicitlyDeclared);
|
2008-11-06 04:51:48 +08:00
|
|
|
}
|
|
|
|
|
2008-11-08 04:08:42 +08:00
|
|
|
CXXConversionDecl *
|
|
|
|
CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD,
|
2008-11-17 22:58:09 +08:00
|
|
|
SourceLocation L, DeclarationName N,
|
2008-11-08 04:08:42 +08:00
|
|
|
QualType T, bool isInline, bool isExplicit) {
|
2008-11-17 22:58:09 +08:00
|
|
|
assert(N.getNameKind() == DeclarationName::CXXConversionFunctionName &&
|
|
|
|
"Name must refer to a conversion function");
|
2009-01-28 05:25:57 +08:00
|
|
|
return new (C) CXXConversionDecl(RD, L, N, T, isInline, isExplicit);
|
2008-11-08 04:08:42 +08:00
|
|
|
}
|
|
|
|
|
Change struct forward declarations and definitions to use unique RecordDecls, as opposed to creating a single RecordDecl and reusing it.
This change effects both RecordDecls and CXXRecordDecls, but does not effect EnumDecls (yet).
The motivation of this patch is as follows:
- Capture more source information, necessary for refactoring/rewriting clients.
- Pave the way to resolve ownership issues with RecordDecls with the forthcoming
addition of DeclGroups.
Current caveats:
- Until DeclGroups are in place, we will leak RecordDecls not explicitly
referenced by the AST. For example:
typedef struct { ... } x;
The RecordDecl for the struct will be leaked because the TypedefDecl doesn't
refer to it. This will be solved with DeclGroups.
- This patch also (temporarily) breaks CodeGen. More below.
High-level changes:
- As before, TagType still refers to a TagDecl, but it doesn't own it. When
a struct/union/class is first referenced, a RecordType and RecordDecl are
created for it, and the RecordType refers to that RecordDecl. Later, if
a new RecordDecl is created, the pointer to a RecordDecl in RecordType is
updated to point to the RecordDecl that defines the struct/union/class.
- TagDecl and RecordDecl now how a method 'getDefinition()' to return the
TagDecl*/RecordDecl* that refers to the TagDecl* that defines a particular
enum/struct/class/union. This is useful from going from a RecordDecl* that
defines a forward declaration to the RecordDecl* that provides the actual
definition. Note that this also works for EnumDecls, except that in this case
there is no distinction between forward declarations and definitions (yet).
- Clients should no longer assume that 'isDefinition()' returns true from a
RecordDecl if the corresponding struct/union/class has been defined.
isDefinition() only returns true if a particular RecordDecl is the defining
Decl. Use 'getDefinition()' instead to determine if a struct has been defined.
- The main changes to Sema happen in ActOnTag. To make the changes more
incremental, I split off the processing of enums and structs et al into two
code paths. Enums use the original code path (which is in ActOnTag) and
structs use the ActOnTagStruct. Eventually the two code paths will be merged,
but the idea was to preserve the original logic both for comparison and not to
change the logic for both enums and structs all at once.
- There is NO CHAINING of RecordDecls for the same RecordType. All RecordDecls
that correspond to the same type simply have a pointer to that type. If we
need to figure out what are all the RecordDecls for a given type we can build
a backmap.
- The diff in CXXRecordDecl.[cpp,h] is actually very small; it just mimics the
changes to RecordDecl. For some reason 'svn' marks the entire file as changed.
Why is CodeGen broken:
- Codegen assumes that there is an equivalence between RecordDecl* and
RecordType*. This was true before because we only created one RecordDecl* for
a given RecordType*, but it is no longer true. I believe this shouldn't be too
hard to change, but the patch was big enough as it is.
I have tested this patch on both the clang test suite, and by running the static analyzer over Postgresql and a large Apple-internal project (mix of Objective-C and C).
llvm-svn: 55839
2008-09-06 01:16:31 +08:00
|
|
|
CXXClassVarDecl *CXXClassVarDecl::Create(ASTContext &C, CXXRecordDecl *RD,
|
|
|
|
SourceLocation L, IdentifierInfo *Id,
|
2009-01-20 09:17:11 +08:00
|
|
|
QualType T) {
|
2009-01-28 05:25:57 +08:00
|
|
|
return new (C) CXXClassVarDecl(RD, L, Id, T);
|
Change struct forward declarations and definitions to use unique RecordDecls, as opposed to creating a single RecordDecl and reusing it.
This change effects both RecordDecls and CXXRecordDecls, but does not effect EnumDecls (yet).
The motivation of this patch is as follows:
- Capture more source information, necessary for refactoring/rewriting clients.
- Pave the way to resolve ownership issues with RecordDecls with the forthcoming
addition of DeclGroups.
Current caveats:
- Until DeclGroups are in place, we will leak RecordDecls not explicitly
referenced by the AST. For example:
typedef struct { ... } x;
The RecordDecl for the struct will be leaked because the TypedefDecl doesn't
refer to it. This will be solved with DeclGroups.
- This patch also (temporarily) breaks CodeGen. More below.
High-level changes:
- As before, TagType still refers to a TagDecl, but it doesn't own it. When
a struct/union/class is first referenced, a RecordType and RecordDecl are
created for it, and the RecordType refers to that RecordDecl. Later, if
a new RecordDecl is created, the pointer to a RecordDecl in RecordType is
updated to point to the RecordDecl that defines the struct/union/class.
- TagDecl and RecordDecl now how a method 'getDefinition()' to return the
TagDecl*/RecordDecl* that refers to the TagDecl* that defines a particular
enum/struct/class/union. This is useful from going from a RecordDecl* that
defines a forward declaration to the RecordDecl* that provides the actual
definition. Note that this also works for EnumDecls, except that in this case
there is no distinction between forward declarations and definitions (yet).
- Clients should no longer assume that 'isDefinition()' returns true from a
RecordDecl if the corresponding struct/union/class has been defined.
isDefinition() only returns true if a particular RecordDecl is the defining
Decl. Use 'getDefinition()' instead to determine if a struct has been defined.
- The main changes to Sema happen in ActOnTag. To make the changes more
incremental, I split off the processing of enums and structs et al into two
code paths. Enums use the original code path (which is in ActOnTag) and
structs use the ActOnTagStruct. Eventually the two code paths will be merged,
but the idea was to preserve the original logic both for comparison and not to
change the logic for both enums and structs all at once.
- There is NO CHAINING of RecordDecls for the same RecordType. All RecordDecls
that correspond to the same type simply have a pointer to that type. If we
need to figure out what are all the RecordDecls for a given type we can build
a backmap.
- The diff in CXXRecordDecl.[cpp,h] is actually very small; it just mimics the
changes to RecordDecl. For some reason 'svn' marks the entire file as changed.
Why is CodeGen broken:
- Codegen assumes that there is an equivalence between RecordDecl* and
RecordType*. This was true before because we only created one RecordDecl* for
a given RecordType*, but it is no longer true. I believe this shouldn't be too
hard to change, but the patch was big enough as it is.
I have tested this patch on both the clang test suite, and by running the static analyzer over Postgresql and a large Apple-internal project (mix of Objective-C and C).
llvm-svn: 55839
2008-09-06 01:16:31 +08:00
|
|
|
}
|
2008-10-22 00:13:35 +08:00
|
|
|
|
|
|
|
OverloadedFunctionDecl *
|
|
|
|
OverloadedFunctionDecl::Create(ASTContext &C, DeclContext *DC,
|
2008-11-17 22:58:09 +08:00
|
|
|
DeclarationName N) {
|
2009-01-28 05:25:57 +08:00
|
|
|
return new (C) OverloadedFunctionDecl(DC, N);
|
2008-10-22 00:13:35 +08:00
|
|
|
}
|
2008-11-05 00:51:42 +08:00
|
|
|
|
|
|
|
LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
|
2009-01-06 03:45:36 +08:00
|
|
|
DeclContext *DC,
|
2008-11-05 00:51:42 +08:00
|
|
|
SourceLocation L,
|
2009-01-06 03:45:36 +08:00
|
|
|
LanguageIDs Lang, bool Braces) {
|
2009-01-28 05:25:57 +08:00
|
|
|
return new (C) LinkageSpecDecl(DC, L, Lang, Braces);
|
2008-12-17 06:23:02 +08:00
|
|
|
}
|
2009-02-04 03:21:40 +08:00
|
|
|
|
|
|
|
UsingDirectiveDecl *UsingDirectiveDecl::Create(ASTContext &C, DeclContext *DC,
|
|
|
|
SourceLocation L,
|
|
|
|
SourceLocation NamespaceLoc,
|
|
|
|
SourceLocation IdentLoc,
|
|
|
|
NamespaceDecl *Used,
|
|
|
|
DeclContext *CommonAncestor) {
|
|
|
|
return new (C) UsingDirectiveDecl(DC, L, NamespaceLoc, IdentLoc,
|
|
|
|
Used, CommonAncestor);
|
|
|
|
}
|
|
|
|
|