[cfe-commits] r103497 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExprCXX.cpp test/CXX/class.access/p4.cpp test/SemaCXX/default-assignment-operator.cpp test/SemaTemplate/virtual-member-functions.cpp

Daniel Dunbar daniel at zuster.org
Tue May 11 14:32:49 PDT 2010


This seems to have broken bootstrap, on x86_64-apple-darwin10 at
least. I'm reverting it for now...
--
llvm[2]: Linking Release executable tblgen (without symbols)
Undefined symbols:
  "__ZNK4llvm2cl6parserI10ActionTypeE14getDescriptionEj", referenced from:
      __ZTVN4llvm2cl6parserI10ActionTypeEE in TableGen.o
  "__ZNK4llvm2cl6parserI10ActionTypeE13getNumOptionsEv", referenced from:
      __ZTVN4llvm2cl6parserI10ActionTypeEE in TableGen.o
  "__ZNK4llvm2cl6parserI10ActionTypeE9getOptionEj", referenced from:
      __ZTVN4llvm2cl6parserI10ActionTypeEE in TableGen.o
ld: symbol(s) not found
--

 - Daniel

On Tue, May 11, 2010 at 1:24 PM, Douglas Gregor <dgregor at apple.com> wrote:
> Author: dgregor
> Date: Tue May 11 15:24:17 2010
> New Revision: 103497
>
> URL: http://llvm.org/viewvc/llvm-project?rev=103497&view=rev
> Log:
> Do not mark the virtual members of an implicitly-instantiated class as
> referenced unless we see one of them defined (or the key function
> defined, if it as one) or if we need the vtable for something. Fixes
> PR7114.
>
> Modified:
>    cfe/trunk/lib/Sema/Sema.h
>    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
>    cfe/trunk/lib/Sema/SemaExprCXX.cpp
>    cfe/trunk/test/CXX/class.access/p4.cpp
>    cfe/trunk/test/SemaCXX/default-assignment-operator.cpp
>    cfe/trunk/test/SemaTemplate/virtual-member-functions.cpp
>
> Modified: cfe/trunk/lib/Sema/Sema.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=103497&r1=103496&r2=103497&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/Sema.h (original)
> +++ cfe/trunk/lib/Sema/Sema.h Tue May 11 15:24:17 2010
> @@ -2563,11 +2563,19 @@
>   llvm::SmallVector<std::pair<CXXRecordDecl *, SourceLocation>, 4>
>     ClassesWithUnmarkedVirtualMembers;
>
> +  /// \brief Contains the set of classes with unmarked virtual members
> +  /// that require a vtable.
> +  llvm::SmallPtrSet<CXXRecordDecl *, 4> UnmarkedClassesRequiringVtable;
> +
>   /// MaybeMarkVirtualMembersReferenced - If the passed in method is the
>   /// key function of the record decl, will mark virtual member functions as
>   /// referenced.
>   void MaybeMarkVirtualMembersReferenced(SourceLocation Loc, CXXMethodDecl *MD);
>
> +  /// \brief If the given class does not have a key function, mark its
> +  /// virtual members as referenced.
> +  void MaybeMarkVirtualMembersReferenced(SourceLocation Loc, CXXRecordDecl *RD);
> +
>   /// MarkVirtualMembersReferenced - Will mark all virtual members of the given
>   /// CXXRecordDecl referenced.
>   void MarkVirtualMembersReferenced(SourceLocation Loc,
> @@ -3571,6 +3579,24 @@
>     }
>   };
>
> +  /// \brief RAII class that determines when any errors have occurred
> +  /// between the time the instance was created and the time it was
> +  /// queried.
> +  class ErrorTrap {
> +    Sema &SemaRef;
> +    unsigned PrevErrors;
> +
> +  public:
> +    explicit ErrorTrap(Sema &SemaRef)
> +      : SemaRef(SemaRef), PrevErrors(SemaRef.getDiagnostics().getNumErrors()) {}
> +
> +    /// \brief Determine whether any errors have occurred since this
> +    /// object instance was created.
> +    bool hasErrorOccurred() const {
> +      return SemaRef.getDiagnostics().getNumErrors() > PrevErrors;
> +    }
> +  };
> +
>   /// \brief A stack-allocated class that identifies which local
>   /// variable declaration instantiations are present in this scope.
>   ///
>
> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=103497&r1=103496&r2=103497&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue May 11 15:24:17 2010
> @@ -4146,7 +4146,9 @@
>   assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor");
>
>   ImplicitlyDefinedFunctionScope Scope(*this, Constructor);
> -  if (SetBaseOrMemberInitializers(Constructor, 0, 0, /*AnyErrors=*/false)) {
> +  ErrorTrap Trap(*this);
> +  if (SetBaseOrMemberInitializers(Constructor, 0, 0, /*AnyErrors=*/false) ||
> +      Trap.hasErrorOccurred()) {
>     Diag(CurrentLocation, diag::note_member_synthesized_at)
>       << CXXConstructor << Context.getTagDeclType(ClassDecl);
>     Constructor->setInvalidDecl();
> @@ -4162,14 +4164,16 @@
>   CXXRecordDecl *ClassDecl = Destructor->getParent();
>   assert(ClassDecl && "DefineImplicitDestructor - invalid destructor");
>
> +  if (Destructor->isInvalidDecl())
> +    return;
> +
>   ImplicitlyDefinedFunctionScope Scope(*this, Destructor);
>
> +  ErrorTrap Trap(*this);
>   MarkBaseAndMemberDestructorsReferenced(Destructor->getLocation(),
>                                          Destructor->getParent());
>
> -  // FIXME: If CheckDestructor fails, we should emit a note about where the
> -  // implicit destructor was needed.
> -  if (CheckDestructor(Destructor)) {
> +  if (CheckDestructor(Destructor) || Trap.hasErrorOccurred()) {
>     Diag(CurrentLocation, diag::note_member_synthesized_at)
>       << CXXDestructor << Context.getTagDeclType(ClassDecl);
>
> @@ -4396,6 +4400,7 @@
>   CopyAssignOperator->setUsed();
>
>   ImplicitlyDefinedFunctionScope Scope(*this, CopyAssignOperator);
> +  ErrorTrap Trap(*this);
>
>   // C++0x [class.copy]p30:
>   //   The implicitly-defined or explicitly-defaulted copy assignment operator
> @@ -4619,6 +4624,13 @@
>     }
>   }
>
> +  if (Trap.hasErrorOccurred()) {
> +    Diag(CurrentLocation, diag::note_member_synthesized_at)
> +      << CXXCopyAssignment << Context.getTagDeclType(ClassDecl);
> +    CopyAssignOperator->setInvalidDecl();
> +    return;
> +  }
> +
>   if (Invalid) {
>     CopyAssignOperator->setInvalidDecl();
>     return;
> @@ -4642,8 +4654,10 @@
>   assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor");
>
>   ImplicitlyDefinedFunctionScope Scope(*this, CopyConstructor);
> +  ErrorTrap Trap(*this);
>
> -  if (SetBaseOrMemberInitializers(CopyConstructor, 0, 0, /*AnyErrors=*/false)) {
> +  if (SetBaseOrMemberInitializers(CopyConstructor, 0, 0, /*AnyErrors=*/false) ||
> +      Trap.hasErrorOccurred()) {
>     Diag(CurrentLocation, diag::note_member_synthesized_at)
>       << CXXCopyConstructor << Context.getTagDeclType(ClassDecl);
>     CopyConstructor->setInvalidDecl();
> @@ -6068,12 +6082,32 @@
>     return;
>
>   TemplateSpecializationKind kind = RD->getTemplateSpecializationKind();
> -  if (kind == TSK_ImplicitInstantiation)
> -    ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(RD, Loc));
> -  else
> +  if (kind == TSK_ImplicitInstantiation) {
> +    CXXRecordDecl *CanonRD = cast<CXXRecordDecl>(RD->getCanonicalDecl());
> +    if (UnmarkedClassesRequiringVtable.insert(CanonRD))
> +      ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(RD, Loc));
> +  } else
>     MarkVirtualMembersReferenced(Loc, RD);
>  }
>
> +void Sema::MaybeMarkVirtualMembersReferenced(SourceLocation Loc,
> +                                             CXXRecordDecl *RD) {
> +  if (RD->isDependentContext() || !RD->isDynamicClass())
> +    return;
> +
> +  if (RD->getTemplateSpecializationKind() != TSK_ImplicitInstantiation)
> +    return;
> +
> +  // Classes with a key function will be dealt with when we see the
> +  // definition of the key function.
> +  if (Context.getKeyFunction(RD))
> +    return;
> +
> +  CXXRecordDecl *CanonRD = cast<CXXRecordDecl>(RD->getCanonicalDecl());
> +  if (UnmarkedClassesRequiringVtable.insert(CanonRD))
> +    ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(RD, Loc));
> +}
> +
>  bool Sema::ProcessPendingClassesWithUnmarkedVirtualMembers() {
>   if (ClassesWithUnmarkedVirtualMembers.empty())
>     return false;
> @@ -6082,6 +6116,15 @@
>     CXXRecordDecl *RD = ClassesWithUnmarkedVirtualMembers.back().first;
>     SourceLocation Loc = ClassesWithUnmarkedVirtualMembers.back().second;
>     ClassesWithUnmarkedVirtualMembers.pop_back();
> +
> +    // If an implicitly-instantiated class doesn't require a vtable,
> +    // don't mark its virtual members as referenced.
> +    if (RD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) {
> +      CXXRecordDecl *CanonRD = cast<CXXRecordDecl>(RD->getCanonicalDecl());
> +      if (!UnmarkedClassesRequiringVtable.count(CanonRD))
> +        continue;
> +    }
> +
>     MarkVirtualMembersReferenced(Loc, RD);
>   }
>
>
> Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=103497&r1=103496&r2=103497&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue May 11 15:24:17 2010
> @@ -287,7 +287,7 @@
>   if (T->getAs<RecordType>() &&
>       RequireCompleteType(TypeidLoc, T, diag::err_incomplete_typeid))
>     return ExprError();
> -
> +
>   return Owned(new (Context) CXXTypeidExpr(TypeInfoType.withConst(),
>                                            Operand,
>                                            SourceRange(TypeidLoc, RParenLoc)));
> @@ -314,8 +314,10 @@
>       //   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)
> +      if (RecordD->isPolymorphic() && E->isLvalue(Context) == Expr::LV_Valid) {
>         isUnevaluatedOperand = false;
> +        MaybeMarkVirtualMembersReferenced(TypeidLoc, RecordD);
> +      }
>     }
>
>     // C++ [expr.typeid]p4:
> @@ -445,6 +447,14 @@
>   if (Res.isInvalid())
>     return true;
>   E = Res.takeAs<Expr>();
> +
> +  if (const RecordType *RecordTy = Ty->getAs<RecordType>()) {
> +    // If we're throwing a polymorphic class, we need to make sure
> +    // there is a vtable.
> +    MaybeMarkVirtualMembersReferenced(ThrowLoc,
> +                                      cast<CXXRecordDecl>(RecordTy->getDecl()));
> +  }
> +
>   return false;
>  }
>
>
> Modified: cfe/trunk/test/CXX/class.access/p4.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class.access/p4.cpp?rev=103497&r1=103496&r2=103497&view=diff
> ==============================================================================
> --- cfe/trunk/test/CXX/class.access/p4.cpp (original)
> +++ cfe/trunk/test/CXX/class.access/p4.cpp Tue May 11 15:24:17 2010
> @@ -97,7 +97,7 @@
>   A A::foo; // okay
>
>   class B : A { }; // expected-error {{base class 'test2::A' has private constructor}}
> -  B b;
> +  B b; // expected-note{{implicit default constructor}}
>
>   class C : virtual A {
>   public:
> @@ -105,7 +105,7 @@
>   };
>
>   class D : C { }; // expected-error {{inherited virtual base class 'test2::A' has private constructor}}
> -  D d;
> +  D d; // expected-note{{implicit default constructor}}
>  }
>
>  // Implicit destructor calls.
> @@ -143,13 +143,15 @@
>   };
>
>   class Derived3 : // expected-error 2 {{inherited virtual base class 'Base<2>' has private destructor}} \
> -                   // expected-error 2 {{inherited virtual base class 'Base<3>' has private destructor}}
> +                   // expected-error 2 {{inherited virtual base class 'Base<3>' has private destructor}} \
> +    // expected-note 2{{implicit default constructor}}
>     Base<0>,  // expected-error 2 {{base class 'Base<0>' has private destructor}}
>     virtual Base<1>, // expected-error 2 {{base class 'Base<1>' has private destructor}}
>     Base2, // expected-error 2 {{base class 'test3::Base2' has private destructor}}
>     virtual Base3
> -  {};
> -  Derived3 d3;
> +  {};
> +  Derived3 d3; // expected-note {{implicit default constructor}}\
> +               // expected-note{{implicit default destructor}}}
>  }
>
>  // Conversion functions.
> @@ -205,13 +207,13 @@
>   class Test1 { A a; }; // expected-error {{private member}}
>   void test1() {
>     Test1 a;
> -    a = Test1();
> +    a = Test1(); // expected-note{{implicit default copy}}
>   }
>
>   class Test2 : A {}; // expected-error {{private member}}
>   void test2() {
>     Test2 a;
> -    a = Test2();
> +    a = Test2(); // expected-note{{implicit default copy}}
>   }
>  }
>
> @@ -224,12 +226,12 @@
>
>   class Test1 { A a; }; // expected-error {{field of type 'test6::A' has private copy constructor}}
>   void test1(const Test1 &t) {
> -    Test1 a = t;
> +    Test1 a = t; // expected-note{{implicit default copy}}
>   }
>
>   class Test2 : A {}; // expected-error {{base class 'test6::A' has private copy constructor}}
>   void test2(const Test2 &t) {
> -    Test2 a = t;
> +    Test2 a = t; // expected-note{{implicit default copy}}
>   }
>  }
>
>
> Modified: cfe/trunk/test/SemaCXX/default-assignment-operator.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/default-assignment-operator.cpp?rev=103497&r1=103496&r2=103497&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/default-assignment-operator.cpp (original)
> +++ cfe/trunk/test/SemaCXX/default-assignment-operator.cpp Tue May 11 15:24:17 2010
> @@ -7,7 +7,8 @@
>  };
>
>  class X  : Base {  // // expected-error {{cannot define the implicit default assignment operator for 'X', because non-static const member 'cint' can't use default assignment operator}} \
> -// expected-note{{assignment operator for 'Base' first required here}}
> +// expected-note{{assignment operator for 'Base' first required here}} \
> +  // expected-note{{implicit default copy assignment operator}}
>  public:
>   X();
>   const int cint;  // expected-note {{declared here}}
> @@ -28,7 +29,8 @@
>
>  // Test1
>  void f(X x, const X cx) {
> -  x = cx; // expected-note{{assignment operator for 'X' first required here}}
> +  x = cx; // expected-note{{assignment operator for 'X' first required here}} \
> +  // expected-note{{implicit default copy assignment operator}}
>   x = cx;
>   z1 = z2;
>  }
> @@ -84,7 +86,9 @@
>  E1 e1, e2;
>
>  void j() {
> -  e1 = e2; // expected-note{{assignment operator for 'E1' first required here}}
> +  // FIXME: duplicated!
> +  e1 = e2; // expected-note{{assignment operator for 'E1' first required here}} \
> +  // expected-note{{implicit default copy assignment operator}}
>  }
>
>  namespace ProtectedCheck {
> @@ -101,7 +105,8 @@
>     X x;
>   };
>
> -  void f(Z z) { z = z; } //
> +  void f(Z z) { z = z; }  // expected-note{{implicit default copy assignment operator}}
> +
>  }
>
>  namespace MultiplePaths {
>
> Modified: cfe/trunk/test/SemaTemplate/virtual-member-functions.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/virtual-member-functions.cpp?rev=103497&r1=103496&r2=103497&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaTemplate/virtual-member-functions.cpp (original)
> +++ cfe/trunk/test/SemaTemplate/virtual-member-functions.cpp Tue May 11 15:24:17 2010
> @@ -53,3 +53,26 @@
>  }
>
>  HasOutOfLineKey<int> out_of_line;
> +
> +namespace std {
> +  class type_info;
> +}
> +
> +namespace PR7114 {
> +  class A { virtual ~A(); }; // expected-note{{declared private here}}
> +
> +  template<typename T>
> +  class B {
> +  public:
> +    class Inner : public A { }; // expected-error{{base class 'PR7114::A' has private destructor}}
> +    static Inner i;
> +    static const unsigned value = sizeof(i) == 4;
> +  };
> +
> +  int f() { return B<int>::value; }
> +
> +  void test_typeid(B<float>::Inner bfi) {
> +    (void)typeid(bfi); // expected-note{{implicit default destructor}}
> +  }
> +}
> +
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>




More information about the cfe-commits mailing list