[cfe-commits] r95330 - in /cfe/trunk: include/clang/AST/DeclCXX.h include/clang/Basic/DiagnosticSemaKinds.td lib/AST/Decl.cpp lib/AST/DeclCXX.cpp lib/CodeGen/CGRTTI.cpp lib/CodeGen/CodeGenTypes.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaLookup.cpp lib/Sema/SemaOverload.cpp
John McCall
rjmccall at apple.com
Thu Feb 4 14:26:27 PST 2010
Author: rjmccall
Date: Thu Feb 4 16:26:26 2010
New Revision: 95330
URL: http://llvm.org/viewvc/llvm-project?rev=95330&view=rev
Log:
Extract a common structure for holding information about the definition
of a C++ record. Exposed a lot of problems where various routines were
silently doing The Wrong Thing (or The Acceptable Thing in The Wrong Order)
when presented with a non-definition. Also cuts down on memory usage.
Modified:
cfe/trunk/include/clang/AST/DeclCXX.h
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/AST/Decl.cpp
cfe/trunk/lib/AST/DeclCXX.cpp
cfe/trunk/lib/CodeGen/CGRTTI.cpp
cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/lib/Sema/SemaLookup.cpp
cfe/trunk/lib/Sema/SemaOverload.cpp
Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=95330&r1=95329&r2=95330&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Thu Feb 4 16:26:26 2010
@@ -174,115 +174,137 @@
/// 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;
-
- /// UserDeclaredCopyConstructor - True when this class has a
- /// user-declared copy constructor.
- bool UserDeclaredCopyConstructor : 1;
-
- /// UserDeclaredCopyAssignment - True when this class has a
- /// user-declared copy assignment operator.
- bool UserDeclaredCopyAssignment : 1;
-
- /// UserDeclaredDestructor - True when this class has a
- /// user-declared destructor.
- bool UserDeclaredDestructor : 1;
-
- /// Aggregate - True when this class is an aggregate.
- bool Aggregate : 1;
-
- /// PlainOldData - True when this class is a POD-type.
- bool PlainOldData : 1;
-
- /// Empty - true when this class is empty for traits purposes, i.e. has no
- /// data members other than 0-width bit-fields, has no virtual function/base,
- /// and doesn't inherit from a non-empty class. Doesn't take union-ness into
- /// account.
- bool Empty : 1;
-
- /// Polymorphic - True when this class is polymorphic, i.e. has at least one
- /// virtual member or derives from a polymorphic class.
- bool Polymorphic : 1;
-
- /// Abstract - True when this class is abstract, i.e. has at least one
- /// pure virtual function, (that can come from a base class).
- bool Abstract : 1;
-
- /// HasTrivialConstructor - True when this class has a trivial constructor.
- ///
- /// C++ [class.ctor]p5. A constructor is trivial if it is an
- /// implicitly-declared default constructor and if:
- /// * its class has no virtual functions and no virtual base classes, and
- /// * all the direct base classes of its class have trivial constructors, and
- /// * for all the nonstatic data members of its class that are of class type
- /// (or array thereof), each such class has a trivial constructor.
- bool HasTrivialConstructor : 1;
-
- /// HasTrivialCopyConstructor - True when this class has a trivial copy
- /// constructor.
- ///
- /// C++ [class.copy]p6. A copy constructor for class X is trivial
- /// if it is implicitly declared and if
- /// * class X has no virtual functions and no virtual base classes, and
- /// * each direct base class of X has a trivial copy constructor, and
- /// * for all the nonstatic data members of X that are of class type (or
- /// array thereof), each such class type has a trivial copy constructor;
- /// otherwise the copy constructor is non-trivial.
- bool HasTrivialCopyConstructor : 1;
-
- /// HasTrivialCopyAssignment - True when this class has a trivial copy
- /// assignment operator.
- ///
- /// C++ [class.copy]p11. A copy assignment operator for class X is
- /// trivial if it is implicitly declared and if
- /// * class X has no virtual functions and no virtual base classes, and
- /// * each direct base class of X has a trivial copy assignment operator, and
- /// * for all the nonstatic data members of X that are of class type (or
- /// array thereof), each such class type has a trivial copy assignment
- /// operator;
- /// otherwise the copy assignment operator is non-trivial.
- bool HasTrivialCopyAssignment : 1;
-
- /// HasTrivialDestructor - True when this class has a trivial destructor.
- ///
- /// C++ [class.dtor]p3. A destructor is trivial if it is an
- /// implicitly-declared destructor and if:
- /// * all of the direct base classes of its class have trivial destructors
- /// and
- /// * for all of the non-static data members of its class that are of class
- /// type (or array thereof), each such class has a trivial destructor.
- bool HasTrivialDestructor : 1;
-
- /// ComputedVisibleConversions - True when visible conversion functions are
- /// already computed and are available.
- bool ComputedVisibleConversions : 1;
-
- /// Bases - Base classes of this class.
- /// FIXME: This is wasted space for a union.
- CXXBaseSpecifier *Bases;
-
- /// NumBases - The number of base class specifiers in Bases.
- unsigned NumBases;
-
- /// VBases - direct and indirect virtual base classes of this class.
- CXXBaseSpecifier *VBases;
-
- /// NumVBases - The number of virtual base class specifiers in VBases.
- unsigned NumVBases;
-
- /// Conversions - Overload set containing the conversion functions
- /// of this C++ class (but not its inherited conversion
- /// functions). Each of the entries in this overload set is a
- /// CXXConversionDecl.
- UnresolvedSet<4> Conversions;
-
- /// VisibleConversions - Overload set containing the conversion functions
- /// of this C++ class and all those inherited conversion functions that
- /// are visible in this class. Each of the entries in this overload set is
- /// a CXXConversionDecl or a FunctionTemplateDecl.
- UnresolvedSet<4> VisibleConversions;
+
+ friend void TagDecl::startDefinition();
+
+ struct DefinitionData {
+ DefinitionData(CXXRecordDecl *D);
+
+ /// UserDeclaredConstructor - True when this class has a
+ /// user-declared constructor.
+ bool UserDeclaredConstructor : 1;
+
+ /// UserDeclaredCopyConstructor - True when this class has a
+ /// user-declared copy constructor.
+ bool UserDeclaredCopyConstructor : 1;
+
+ /// UserDeclaredCopyAssignment - True when this class has a
+ /// user-declared copy assignment operator.
+ bool UserDeclaredCopyAssignment : 1;
+
+ /// UserDeclaredDestructor - True when this class has a
+ /// user-declared destructor.
+ bool UserDeclaredDestructor : 1;
+
+ /// Aggregate - True when this class is an aggregate.
+ bool Aggregate : 1;
+
+ /// PlainOldData - True when this class is a POD-type.
+ bool PlainOldData : 1;
+
+ /// Empty - true when this class is empty for traits purposes,
+ /// i.e. has no data members other than 0-width bit-fields, has no
+ /// virtual function/base, and doesn't inherit from a non-empty
+ /// class. Doesn't take union-ness into account.
+ bool Empty : 1;
+
+ /// Polymorphic - True when this class is polymorphic, i.e. has at
+ /// least one virtual member or derives from a polymorphic class.
+ bool Polymorphic : 1;
+
+ /// Abstract - True when this class is abstract, i.e. has at least
+ /// one pure virtual function, (that can come from a base class).
+ bool Abstract : 1;
+
+ /// HasTrivialConstructor - True when this class has a trivial constructor.
+ ///
+ /// C++ [class.ctor]p5. A constructor is trivial if it is an
+ /// implicitly-declared default constructor and if:
+ /// * its class has no virtual functions and no virtual base classes, and
+ /// * all the direct base classes of its class have trivial constructors, and
+ /// * for all the nonstatic data members of its class that are of class type
+ /// (or array thereof), each such class has a trivial constructor.
+ bool HasTrivialConstructor : 1;
+
+ /// HasTrivialCopyConstructor - True when this class has a trivial copy
+ /// constructor.
+ ///
+ /// C++ [class.copy]p6. A copy constructor for class X is trivial
+ /// if it is implicitly declared and if
+ /// * class X has no virtual functions and no virtual base classes, and
+ /// * each direct base class of X has a trivial copy constructor, and
+ /// * for all the nonstatic data members of X that are of class type (or
+ /// array thereof), each such class type has a trivial copy constructor;
+ /// otherwise the copy constructor is non-trivial.
+ bool HasTrivialCopyConstructor : 1;
+
+ /// HasTrivialCopyAssignment - True when this class has a trivial copy
+ /// assignment operator.
+ ///
+ /// C++ [class.copy]p11. A copy assignment operator for class X is
+ /// trivial if it is implicitly declared and if
+ /// * class X has no virtual functions and no virtual base classes, and
+ /// * each direct base class of X has a trivial copy assignment operator, and
+ /// * for all the nonstatic data members of X that are of class type (or
+ /// array thereof), each such class type has a trivial copy assignment
+ /// operator;
+ /// otherwise the copy assignment operator is non-trivial.
+ bool HasTrivialCopyAssignment : 1;
+
+ /// HasTrivialDestructor - True when this class has a trivial destructor.
+ ///
+ /// C++ [class.dtor]p3. A destructor is trivial if it is an
+ /// implicitly-declared destructor and if:
+ /// * all of the direct base classes of its class have trivial destructors
+ /// and
+ /// * for all of the non-static data members of its class that are of class
+ /// type (or array thereof), each such class has a trivial destructor.
+ bool HasTrivialDestructor : 1;
+
+ /// ComputedVisibleConversions - True when visible conversion functions are
+ /// already computed and are available.
+ bool ComputedVisibleConversions : 1;
+
+ /// Bases - Base classes of this class.
+ /// FIXME: This is wasted space for a union.
+ CXXBaseSpecifier *Bases;
+
+ /// NumBases - The number of base class specifiers in Bases.
+ unsigned NumBases;
+
+ /// VBases - direct and indirect virtual base classes of this class.
+ CXXBaseSpecifier *VBases;
+
+ /// NumVBases - The number of virtual base class specifiers in VBases.
+ unsigned NumVBases;
+
+ /// Conversions - Overload set containing the conversion functions
+ /// of this C++ class (but not its inherited conversion
+ /// functions). Each of the entries in this overload set is a
+ /// CXXConversionDecl.
+ UnresolvedSet<4> Conversions;
+
+ /// VisibleConversions - Overload set containing the conversion
+ /// functions of this C++ class and all those inherited conversion
+ /// functions that are visible in this class. Each of the entries
+ /// in this overload set is a CXXConversionDecl or a
+ /// FunctionTemplateDecl.
+ UnresolvedSet<4> VisibleConversions;
+
+ /// Definition - The declaration which defines this record.
+ CXXRecordDecl *Definition;
+
+ } *DefinitionData;
+
+ struct DefinitionData &data() {
+ assert(DefinitionData && "queried property of class with no definition");
+ return *DefinitionData;
+ }
+
+ const struct DefinitionData &data() const {
+ assert(DefinitionData && "queried property of class with no definition");
+ return *DefinitionData;
+ }
/// \brief The template or declaration that this declaration
/// describes or was instantiated from, respectively.
@@ -336,6 +358,13 @@
return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl());
}
+ CXXRecordDecl *getDefinition(ASTContext& C) const {
+ if (!DefinitionData) return 0;
+ return data().Definition;
+ }
+
+ bool hasDefinition() const { return DefinitionData != 0; }
+
static CXXRecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
SourceLocation TKL = SourceLocation(),
@@ -345,7 +374,7 @@
virtual void Destroy(ASTContext& C);
bool isDynamicClass() const {
- return Polymorphic || NumVBases != 0;
+ return data().Polymorphic || data().NumVBases != 0;
}
/// setBases - Sets the base classes of this struct or class.
@@ -354,12 +383,14 @@
/// getNumBases - Retrieves the number of base classes of this
/// class.
- unsigned getNumBases() const { return NumBases; }
+ unsigned getNumBases() const { return data().NumBases; }
- base_class_iterator bases_begin() { return Bases; }
- base_class_const_iterator bases_begin() const { return Bases; }
- base_class_iterator bases_end() { return Bases + NumBases; }
- base_class_const_iterator bases_end() const { return Bases + NumBases; }
+ base_class_iterator bases_begin() { return data().Bases; }
+ base_class_const_iterator bases_begin() const { return data().Bases; }
+ base_class_iterator bases_end() { return bases_begin() + data().NumBases; }
+ base_class_const_iterator bases_end() const {
+ return bases_begin() + data().NumBases;
+ }
reverse_base_class_iterator bases_rbegin() {
return reverse_base_class_iterator(bases_end());
}
@@ -375,12 +406,14 @@
/// getNumVBases - Retrieves the number of virtual base classes of this
/// class.
- unsigned getNumVBases() const { return NumVBases; }
+ unsigned getNumVBases() const { return data().NumVBases; }
- base_class_iterator vbases_begin() { return VBases; }
- base_class_const_iterator vbases_begin() const { return VBases; }
- base_class_iterator vbases_end() { return VBases + NumVBases; }
- base_class_const_iterator vbases_end() const { return VBases + NumVBases; }
+ base_class_iterator vbases_begin() { return data().VBases; }
+ base_class_const_iterator vbases_begin() const { return data().VBases; }
+ base_class_iterator vbases_end() { return vbases_begin() + data().NumVBases; }
+ base_class_const_iterator vbases_end() const {
+ return vbases_begin() + data().NumVBases;
+ }
reverse_base_class_iterator vbases_rbegin() {
return reverse_base_class_iterator(vbases_end());
}
@@ -445,17 +478,14 @@
/// user-declared constructors. When true, a default constructor
/// will not be implicitly declared.
bool hasUserDeclaredConstructor() const {
- assert((isDefinition() ||
- cast<RecordType>(getTypeForDecl())->isBeingDefined()) &&
- "Incomplete record decl!");
- return UserDeclaredConstructor;
+ return data().UserDeclaredConstructor;
}
/// hasUserDeclaredCopyConstructor - Whether this class has a
/// user-declared copy constructor. When false, a copy constructor
/// will be implicitly declared.
bool hasUserDeclaredCopyConstructor() const {
- return UserDeclaredCopyConstructor;
+ return data().UserDeclaredCopyConstructor;
}
/// addedAssignmentOperator - Notify the class that another assignment
@@ -467,45 +497,45 @@
/// user-declared copy assignment operator. When false, a copy
/// assigment operator will be implicitly declared.
bool hasUserDeclaredCopyAssignment() const {
- return UserDeclaredCopyAssignment;
+ return data().UserDeclaredCopyAssignment;
}
/// hasUserDeclaredDestructor - Whether this class has a
/// user-declared destructor. When false, a destructor will be
/// implicitly declared.
- bool hasUserDeclaredDestructor() const { return UserDeclaredDestructor; }
+ bool hasUserDeclaredDestructor() const {
+ return data().UserDeclaredDestructor;
+ }
/// setUserDeclaredDestructor - Set whether this class has a
/// user-declared destructor. If not set by the time the class is
/// fully defined, a destructor will be implicitly declared.
void setUserDeclaredDestructor(bool UCD) {
- UserDeclaredDestructor = UCD;
+ data().UserDeclaredDestructor = UCD;
}
/// getConversions - Retrieve the overload set containing all of the
/// conversion functions in this class.
UnresolvedSetImpl *getConversionFunctions() {
- assert((this->isDefinition() ||
- cast<RecordType>(getTypeForDecl())->isBeingDefined()) &&
- "getConversionFunctions() called on incomplete type");
- return &Conversions;
+ return &data().Conversions;
}
const UnresolvedSetImpl *getConversionFunctions() const {
- assert((this->isDefinition() ||
- cast<RecordType>(getTypeForDecl())->isBeingDefined()) &&
- "getConversionFunctions() called on incomplete type");
- return &Conversions;
+ return &data().Conversions;
}
typedef UnresolvedSetImpl::iterator conversion_iterator;
- conversion_iterator conversion_begin() const { return Conversions.begin(); }
- conversion_iterator conversion_end() const { return Conversions.end(); }
+ conversion_iterator conversion_begin() const {
+ return getConversionFunctions()->begin();
+ }
+ conversion_iterator conversion_end() const {
+ return getConversionFunctions()->end();
+ }
/// Replaces a conversion function with a new declaration.
///
/// Returns true if the old conversion was found.
bool replaceConversion(const NamedDecl* Old, NamedDecl *New) {
- return Conversions.replace(Old, New);
+ return getConversionFunctions()->replace(Old, New);
}
/// getVisibleConversionFunctions - get all conversion functions visible
@@ -532,11 +562,11 @@
/// [dcl.init.aggr]), which is a class with no user-declared
/// constructors, no private or protected non-static data members,
/// no base classes, and no virtual functions (C++ [dcl.init.aggr]p1).
- bool isAggregate() const { return Aggregate; }
+ bool isAggregate() const { return data().Aggregate; }
/// setAggregate - Set whether this class is an aggregate (C++
/// [dcl.init.aggr]).
- void setAggregate(bool Agg) { Aggregate = Agg; }
+ void setAggregate(bool Agg) { data().Aggregate = Agg; }
/// setMethodAsVirtual - Make input method virtual and set the necesssary
/// special function bits and other bits accordingly.
@@ -546,66 +576,74 @@
/// that is an aggregate that has no non-static non-POD data members, no
/// reference data members, no user-defined copy assignment operator and no
/// user-defined destructor.
- bool isPOD() const { return PlainOldData; }
+ bool isPOD() const { return data().PlainOldData; }
/// setPOD - Set whether this class is a POD-type (C++ [class]p4).
- void setPOD(bool POD) { PlainOldData = POD; }
+ void setPOD(bool POD) { data().PlainOldData = POD; }
/// isEmpty - Whether this class is empty (C++0x [meta.unary.prop]), which
/// means it has a virtual function, virtual base, data member (other than
/// 0-width bit-field) or inherits from a non-empty class. Does NOT include
/// a check for union-ness.
- bool isEmpty() const { return Empty; }
+ bool isEmpty() const { return data().Empty; }
/// Set whether this class is empty (C++0x [meta.unary.prop])
- void setEmpty(bool Emp) { Empty = Emp; }
+ void setEmpty(bool Emp) { data().Empty = Emp; }
/// isPolymorphic - Whether this class is polymorphic (C++ [class.virtual]),
/// which means that the class contains or inherits a virtual function.
- bool isPolymorphic() const { return Polymorphic; }
+ bool isPolymorphic() const { return data().Polymorphic; }
/// setPolymorphic - Set whether this class is polymorphic (C++
/// [class.virtual]).
- void setPolymorphic(bool Poly) { Polymorphic = Poly; }
+ void setPolymorphic(bool Poly) { data().Polymorphic = Poly; }
/// isAbstract - Whether this class is abstract (C++ [class.abstract]),
/// which means that the class contains or inherits a pure virtual function.
- bool isAbstract() const { return Abstract; }
+ bool isAbstract() const { return data().Abstract; }
/// setAbstract - Set whether this class is abstract (C++ [class.abstract])
- void setAbstract(bool Abs) { Abstract = Abs; }
+ void setAbstract(bool Abs) { data().Abstract = Abs; }
// hasTrivialConstructor - Whether this class has a trivial constructor
// (C++ [class.ctor]p5)
- bool hasTrivialConstructor() const { return HasTrivialConstructor; }
+ bool hasTrivialConstructor() const { return data().HasTrivialConstructor; }
// setHasTrivialConstructor - Set whether this class has a trivial constructor
// (C++ [class.ctor]p5)
- void setHasTrivialConstructor(bool TC) { HasTrivialConstructor = TC; }
+ void setHasTrivialConstructor(bool TC) { data().HasTrivialConstructor = TC; }
// hasTrivialCopyConstructor - Whether this class has a trivial copy
// constructor (C++ [class.copy]p6)
- bool hasTrivialCopyConstructor() const { return HasTrivialCopyConstructor; }
+ bool hasTrivialCopyConstructor() const {
+ return data().HasTrivialCopyConstructor;
+ }
// setHasTrivialCopyConstructor - Set whether this class has a trivial
// copy constructor (C++ [class.copy]p6)
- void setHasTrivialCopyConstructor(bool TC) { HasTrivialCopyConstructor = TC; }
+ void setHasTrivialCopyConstructor(bool TC) {
+ data().HasTrivialCopyConstructor = TC;
+ }
// hasTrivialCopyAssignment - Whether this class has a trivial copy
// assignment operator (C++ [class.copy]p11)
- bool hasTrivialCopyAssignment() const { return HasTrivialCopyAssignment; }
+ bool hasTrivialCopyAssignment() const {
+ return data().HasTrivialCopyAssignment;
+ }
// setHasTrivialCopyAssignment - Set whether this class has a
// trivial copy assignment operator (C++ [class.copy]p11)
- void setHasTrivialCopyAssignment(bool TC) { HasTrivialCopyAssignment = TC; }
+ void setHasTrivialCopyAssignment(bool TC) {
+ data().HasTrivialCopyAssignment = TC;
+ }
// hasTrivialDestructor - Whether this class has a trivial destructor
// (C++ [class.dtor]p3)
- bool hasTrivialDestructor() const { return HasTrivialDestructor; }
+ bool hasTrivialDestructor() const { return data().HasTrivialDestructor; }
// setHasTrivialDestructor - Set whether this class has a trivial destructor
// (C++ [class.dtor]p3)
- void setHasTrivialDestructor(bool TC) { HasTrivialDestructor = TC; }
+ void setHasTrivialDestructor(bool TC) { data().HasTrivialDestructor = TC; }
/// \brief If this record is an instantiation of a member class,
/// retrieves the member class from which it was instantiated.
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=95330&r1=95329&r2=95330&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Feb 4 16:26:26 2010
@@ -1706,6 +1706,8 @@
def err_no_member : Error<"no member named %0 in %1">;
def err_member_redeclared : Error<"class member cannot be redeclared">;
+def err_member_def_undefined_record : Error<
+ "out-of-line definition of %0 from class %1 without definition">;
def err_member_def_does_not_match : Error<
"out-of-line definition of %0 does not match any declaration in %1">;
def err_nonstatic_member_out_of_line : Error<
Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=95330&r1=95329&r2=95330&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Thu Feb 4 16:26:26 2010
@@ -1373,6 +1373,16 @@
TagT->decl.setPointer(this);
TagT->decl.setInt(1);
}
+
+ if (isa<CXXRecordDecl>(this)) {
+ CXXRecordDecl *D = cast<CXXRecordDecl>(this);
+ struct CXXRecordDecl::DefinitionData *Data =
+ new (getASTContext()) struct CXXRecordDecl::DefinitionData(D);
+ do {
+ D->DefinitionData = Data;
+ D = cast_or_null<CXXRecordDecl>(D->getPreviousDeclaration());
+ } while (D);
+ }
}
void TagDecl::completeDefinition() {
Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=95330&r1=95329&r2=95330&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Thu Feb 4 16:26:26 2010
@@ -25,18 +25,23 @@
// Decl Allocation/Deallocation Method Implementations
//===----------------------------------------------------------------------===//
-CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
- SourceLocation L, IdentifierInfo *Id,
- CXXRecordDecl *PrevDecl,
- SourceLocation TKL)
- : RecordDecl(K, TK, DC, L, Id, PrevDecl, TKL),
- UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
+CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
+ : UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
UserDeclaredCopyAssignment(false), UserDeclaredDestructor(false),
Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false),
Abstract(false), HasTrivialConstructor(true),
HasTrivialCopyConstructor(true), HasTrivialCopyAssignment(true),
HasTrivialDestructor(true), ComputedVisibleConversions(false),
Bases(0), NumBases(0), VBases(0), NumVBases(0),
+ Definition(D) {
+}
+
+CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ CXXRecordDecl *PrevDecl,
+ SourceLocation TKL)
+ : RecordDecl(K, TK, DC, L, Id, PrevDecl, TKL),
+ DefinitionData(PrevDecl ? PrevDecl->DefinitionData : 0),
TemplateOrInstantiation() { }
CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
@@ -57,8 +62,11 @@
}
void CXXRecordDecl::Destroy(ASTContext &C) {
- C.Deallocate(Bases);
- C.Deallocate(VBases);
+ if (data().Definition == this) {
+ C.Deallocate(data().Bases);
+ C.Deallocate(data().VBases);
+ C.Deallocate(&data());
+ }
this->RecordDecl::Destroy(C);
}
@@ -69,19 +77,19 @@
// C++ [dcl.init.aggr]p1:
// An aggregate is an array or a class (clause 9) with [...]
// no base classes [...].
- Aggregate = false;
+ data().Aggregate = false;
- if (this->Bases)
- C.Deallocate(this->Bases);
+ if (data().Bases)
+ C.Deallocate(data().Bases);
int vbaseCount = 0;
llvm::SmallVector<const CXXBaseSpecifier*, 8> UniqueVbases;
bool hasDirectVirtualBase = false;
- this->Bases = new(C) CXXBaseSpecifier [NumBases];
- this->NumBases = NumBases;
+ data().Bases = new(C) CXXBaseSpecifier [NumBases];
+ data().NumBases = NumBases;
for (unsigned i = 0; i < NumBases; ++i) {
- this->Bases[i] = *Bases[i];
+ data().Bases[i] = *Bases[i];
// Keep track of inherited vbases for this base class.
const CXXBaseSpecifier *Base = Bases[i];
QualType BaseType = Base->getType();
@@ -130,13 +138,13 @@
}
if (vbaseCount > 0) {
// build AST for inhireted, direct or indirect, virtual bases.
- this->VBases = new (C) CXXBaseSpecifier [vbaseCount];
- this->NumVBases = vbaseCount;
+ data().VBases = new (C) CXXBaseSpecifier [vbaseCount];
+ data().NumVBases = vbaseCount;
for (int i = 0; i < vbaseCount; i++) {
QualType QT = UniqueVbases[i]->getType();
CXXRecordDecl *VBaseClassDecl
= cast<CXXRecordDecl>(QT->getAs<RecordType>()->getDecl());
- this->VBases[i] =
+ data().VBases[i] =
CXXBaseSpecifier(VBaseClassDecl->getSourceRange(), true,
VBaseClassDecl->getTagKind() == RecordDecl::TK_class,
UniqueVbases[i]->getAccessSpecifier(), QT);
@@ -239,32 +247,32 @@
CXXConstructorDecl *ConDecl) {
assert(!ConDecl->isImplicit() && "addedConstructor - not for implicit decl");
// Note that we have a user-declared constructor.
- UserDeclaredConstructor = true;
+ data().UserDeclaredConstructor = true;
// C++ [dcl.init.aggr]p1:
// An aggregate is an array or a class (clause 9) with no
// user-declared constructors (12.1) [...].
- Aggregate = false;
+ data().Aggregate = false;
// C++ [class]p4:
// A POD-struct is an aggregate class [...]
- PlainOldData = false;
+ data().PlainOldData = false;
// C++ [class.ctor]p5:
// A constructor is trivial if it is an implicitly-declared default
// constructor.
// FIXME: C++0x: don't do this for "= default" default constructors.
- HasTrivialConstructor = false;
+ data().HasTrivialConstructor = false;
// Note when we have a user-declared copy constructor, which will
// suppress the implicit declaration of a copy constructor.
if (ConDecl->isCopyConstructor()) {
- UserDeclaredCopyConstructor = true;
+ data().UserDeclaredCopyConstructor = true;
// C++ [class.copy]p6:
// A copy constructor is trivial if it is implicitly declared.
// FIXME: C++0x: don't do this for "= default" copy constructors.
- HasTrivialCopyConstructor = false;
+ data().HasTrivialCopyConstructor = false;
}
}
@@ -295,17 +303,17 @@
OpDecl->setCopyAssignment(true);
// Suppress the implicit declaration of a copy constructor.
- UserDeclaredCopyAssignment = true;
+ data().UserDeclaredCopyAssignment = true;
// C++ [class.copy]p11:
// A copy assignment operator is trivial if it is implicitly declared.
// FIXME: C++0x: don't do this for "= default" copy operators.
- HasTrivialCopyAssignment = false;
+ data().HasTrivialCopyAssignment = false;
// C++ [class]p4:
// A POD-struct is an aggregate class that [...] has no user-defined copy
// assignment operator [...].
- PlainOldData = false;
+ data().PlainOldData = false;
}
void
@@ -415,42 +423,42 @@
const UnresolvedSetImpl *CXXRecordDecl::getVisibleConversionFunctions() {
// If root class, all conversions are visible.
if (bases_begin() == bases_end())
- return &Conversions;
+ return &data().Conversions;
// If visible conversion list is already evaluated, return it.
- if (ComputedVisibleConversions)
- return &VisibleConversions;
+ if (data().ComputedVisibleConversions)
+ return &data().VisibleConversions;
llvm::SmallPtrSet<CanQualType, 8> TopConversionsTypeSet;
collectConversionFunctions(TopConversionsTypeSet);
getNestedVisibleConversionFunctions(this, TopConversionsTypeSet,
TopConversionsTypeSet);
- ComputedVisibleConversions = true;
- return &VisibleConversions;
+ data().ComputedVisibleConversions = true;
+ return &data().VisibleConversions;
}
void CXXRecordDecl::addVisibleConversionFunction(
CXXConversionDecl *ConvDecl) {
assert(!ConvDecl->getDescribedFunctionTemplate() &&
"Conversion function templates should cast to FunctionTemplateDecl.");
- VisibleConversions.addDecl(ConvDecl);
+ data().VisibleConversions.addDecl(ConvDecl);
}
void CXXRecordDecl::addVisibleConversionFunction(
FunctionTemplateDecl *ConvDecl) {
assert(isa<CXXConversionDecl>(ConvDecl->getTemplatedDecl()) &&
"Function template is not a conversion function template");
- VisibleConversions.addDecl(ConvDecl);
+ data().VisibleConversions.addDecl(ConvDecl);
}
void CXXRecordDecl::addConversionFunction(CXXConversionDecl *ConvDecl) {
assert(!ConvDecl->getDescribedFunctionTemplate() &&
"Conversion function templates should cast to FunctionTemplateDecl.");
- Conversions.addDecl(ConvDecl);
+ data().Conversions.addDecl(ConvDecl);
}
void CXXRecordDecl::addConversionFunction(FunctionTemplateDecl *ConvDecl) {
assert(isa<CXXConversionDecl>(ConvDecl->getTemplatedDecl()) &&
"Function template is not a conversion function template");
- Conversions.addDecl(ConvDecl);
+ data().Conversions.addDecl(ConvDecl);
}
Modified: cfe/trunk/lib/CodeGen/CGRTTI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRTTI.cpp?rev=95330&r1=95329&r2=95330&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGRTTI.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGRTTI.cpp Thu Feb 4 16:26:26 2010
@@ -256,6 +256,9 @@
if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
+ if (!RD->hasDefinition())
+ return false;
+
if (!RD->isDynamicClass())
return false;
@@ -469,7 +472,7 @@
const CXXRecordDecl *RD =
cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
- if (!RD->getNumBases()) {
+ if (!RD->hasDefinition() || !RD->getNumBases()) {
// abi::__class_type_info.
VtableName = "_ZTVN10__cxxabiv117__class_type_infoE";
} else if (CanUseSingleInheritance(RD)) {
@@ -566,7 +569,7 @@
case Type::Record: {
const CXXRecordDecl *RD =
cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
- if (!RD->getNumBases()) {
+ if (!RD->hasDefinition() || !RD->getNumBases()) {
// We don't need to emit any fields.
break;
}
Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTypes.cpp?rev=95330&r1=95329&r2=95330&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenTypes.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenTypes.cpp Thu Feb 4 16:26:26 2010
@@ -399,18 +399,6 @@
/// enum.
const llvm::Type *CodeGenTypes::ConvertTagDeclType(const TagDecl *TD) {
- // FIXME. This may have to move to a better place.
- if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(TD)) {
- for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
- e = RD->bases_end(); i != e; ++i) {
- if (!i->isVirtual()) {
- const CXXRecordDecl *Base =
- cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
- ConvertTagDeclType(Base);
- }
- }
- }
-
// TagDecl's are not necessarily unique, instead use the (clang)
// type connected to the decl.
const Type *Key =
@@ -446,6 +434,18 @@
const RecordDecl *RD = cast<const RecordDecl>(TD);
+ // Force conversion of non-virtual base classes recursively.
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(TD)) {
+ for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
+ e = RD->bases_end(); i != e; ++i) {
+ if (!i->isVirtual()) {
+ const CXXRecordDecl *Base =
+ cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
+ ConvertTagDeclType(Base);
+ }
+ }
+ }
+
// Layout fields.
CGRecordLayout *Layout = CGRecordLayoutBuilder::ComputeLayout(*this, RD);
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=95330&r1=95329&r2=95330&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Feb 4 16:26:26 2010
@@ -510,9 +510,18 @@
}
static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
+ if (D->isInvalidDecl())
+ return false;
+
if (D->isUsed() || D->hasAttr<UnusedAttr>())
return false;
-
+
+ // White-list anything that isn't a local variable.
+ if (!isa<VarDecl>(D) || isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D) ||
+ !D->getDeclContext()->isFunctionOrMethod())
+ return false;
+
+ // Types of valid local variables should be complete, so this should succeed.
if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
if (const RecordType *RT = VD->getType()->getAs<RecordType>()) {
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
@@ -524,9 +533,7 @@
}
}
- return (isa<VarDecl>(D) && !isa<ParmVarDecl>(D) &&
- !isa<ImplicitParamDecl>(D) &&
- D->getDeclContext()->isFunctionOrMethod());
+ return true;
}
void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
@@ -1903,6 +1910,13 @@
if (!DC->isDependentContext() &&
RequireCompleteDeclContext(D.getCXXScopeSpec()))
return DeclPtrTy();
+
+ if (isa<CXXRecordDecl>(DC) && !cast<CXXRecordDecl>(DC)->hasDefinition()) {
+ Diag(D.getIdentifierLoc(),
+ diag::err_member_def_undefined_record)
+ << Name << DC << D.getCXXScopeSpec().getRange();
+ D.setInvalidType();
+ }
LookupQualifiedName(Previous, DC);
@@ -3020,7 +3034,7 @@
if (D.getCXXScopeSpec().isSet() && !NewFD->isInvalidDecl()) {
// Fake up an access specifier if it's supposed to be a class member.
- if (isa<CXXRecordDecl>(NewFD->getDeclContext()))
+ if (!Redeclaration && isa<CXXRecordDecl>(NewFD->getDeclContext()))
NewFD->setAccess(AS_public);
// An out-of-line member function declaration must also be a
@@ -5212,7 +5226,7 @@
NewFD->setInvalidDecl();
}
- if (getLangOptions().CPlusPlus) {
+ if (!InvalidDecl && getLangOptions().CPlusPlus) {
CXXRecordDecl* CXXRecord = cast<CXXRecordDecl>(Record);
if (!T->isPODType())
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=95330&r1=95329&r2=95330&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Feb 4 16:26:26 2010
@@ -680,7 +680,8 @@
CXXRecordDecl *DerivedRD = cast<CXXRecordDecl>(DerivedRT->getDecl());
CXXRecordDecl *BaseRD = cast<CXXRecordDecl>(BaseRT->getDecl());
- return DerivedRD->isDerivedFrom(BaseRD);
+ // FIXME: instantiate DerivedRD if necessary. We need a PoI for this.
+ return DerivedRD->hasDefinition() && DerivedRD->isDerivedFrom(BaseRD);
}
/// \brief Determine whether the type \p Derived is a C++ class that is
@@ -1998,13 +1999,15 @@
if (!RT)
return false;
- const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
- if (!RD)
- return false;
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
if (CurrentRD && CurrentRD != RD)
return false;
+ // FIXME: is this reasonable? It matches current behavior, but....
+ if (!RD->getDefinition(Context))
+ return false;
+
if (!RD->isAbstract())
return false;
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=95330&r1=95329&r2=95330&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Thu Feb 4 16:26:26 2010
@@ -72,18 +72,17 @@
if (const RecordType *RecordT = T->getAs<RecordType>()) {
CXXRecordDecl *RecordD = cast<CXXRecordDecl>(RecordT->getDecl());
// C++ [expr.typeid]p3:
+ // [...] If the type of the expression is a class type, the class
+ // shall be completely-defined.
+ if (RequireCompleteType(OpLoc, T, diag::err_incomplete_typeid))
+ return ExprError();
+
+ // C++ [expr.typeid]p3:
// When typeid is applied to an expression other than an lvalue of a
// polymorphic class type [...] [the] expression is an unevaluated
// operand. [...]
if (RecordD->isPolymorphic() && E->isLvalue(Context) == Expr::LV_Valid)
isUnevaluatedOperand = false;
- else {
- // C++ [expr.typeid]p3:
- // [...] If the type of the expression is a class type, the class
- // shall be completely-defined.
- if (RequireCompleteType(OpLoc, T, diag::err_incomplete_typeid))
- return ExprError();
- }
}
// C++ [expr.typeid]p4:
@@ -1985,10 +1984,8 @@
if (!RT)
return Owned(E);
- CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
- if (RD->hasTrivialDestructor())
- return Owned(E);
-
+ // If this is the result of a call expression, our source might
+ // actually be a reference, in which case we shouldn't bind.
if (CallExpr *CE = dyn_cast<CallExpr>(E)) {
QualType Ty = CE->getCallee()->getType();
if (const PointerType *PT = Ty->getAs<PointerType>())
@@ -1998,6 +1995,13 @@
if (FTy->getResultType()->isReferenceType())
return Owned(E);
}
+
+ // That should be enough to guarantee that this type is complete.
+ // If it has a trivial destructor, we can avoid the extra copy.
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ if (RD->hasTrivialDestructor())
+ return Owned(E);
+
CXXTemporary *Temp = CXXTemporary::Create(Context,
RD->getDestructor(Context));
ExprTemporaries.push_back(Temp);
Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=95330&r1=95329&r2=95330&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Thu Feb 4 16:26:26 2010
@@ -1406,6 +1406,12 @@
AssociatedClasses);
}
+ // Only recurse into base classes for complete types.
+ if (!Class->hasDefinition()) {
+ // FIXME: we might need to instantiate templates here
+ return;
+ }
+
// Add direct and indirect base classes along with their associated
// namespaces.
llvm::SmallVector<CXXRecordDecl *, 32> Bases;
@@ -2058,6 +2064,9 @@
// Traverse the contexts of inherited C++ classes.
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx)) {
+ if (!Record->hasDefinition())
+ return;
+
for (CXXRecordDecl::base_class_iterator B = Record->bases_begin(),
BEnd = Record->bases_end();
B != BEnd; ++B) {
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=95330&r1=95329&r2=95330&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Thu Feb 4 16:26:26 2010
@@ -3408,6 +3408,9 @@
}
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl());
+ if (!ClassDecl->hasDefinition())
+ return VRQuals;
+
const UnresolvedSetImpl *Conversions =
ClassDecl->getVisibleConversionFunctions();
More information about the cfe-commits
mailing list