[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