]> granicus.if.org Git - clang/commitdiff
Fix PR13784: instantiation of an abstract class in a conditional operator.
authorDavid Blaikie <dblaikie@gmail.com>
Mon, 10 Sep 2012 22:05:41 +0000 (22:05 +0000)
committerDavid Blaikie <dblaikie@gmail.com>
Mon, 10 Sep 2012 22:05:41 +0000 (22:05 +0000)
A couple of missing "RequireNonAbstractType" calls in conditional operator
handling. I looked for opportunities to tie this check in to all relevant
callers of PerformCopyInitialization (couldn't be all callers since this is
called for base subobject copying too, where it's acceptable to copy abstract
types) but the callers varied too much & in many cases had substantial code
or conditionals on the RequireNonAbstractType call, the
PerformCopyInitialization call, or the code between the two calls.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@163555 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaExprCXX.cpp
test/SemaCXX/conditional-expr.cpp

index dc5fc284dcadfae8c60900fed1be5d448476cef2..4dca91db138d5cab8735d0678e0ef676ccd651cf 100644 (file)
@@ -4149,6 +4149,9 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
     ExprResult &NonVoid = LVoid ? RHS : LHS;
     if (NonVoid.get()->getType()->isRecordType() &&
         NonVoid.get()->isGLValue()) {
+      if (RequireNonAbstractType(QuestionLoc, NonVoid.get()->getType(),
+                             diag::err_allocation_of_abstract_type))
+        return QualType();
       InitializedEntity Entity =
           InitializedEntity::InitializeTemporary(NonVoid.get()->getType());
       NonVoid = PerformCopyInitialization(Entity, SourceLocation(), NonVoid);
@@ -4291,7 +4294,11 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
   if (Context.getCanonicalType(LTy) == Context.getCanonicalType(RTy)) {
     if (LTy->isRecordType()) {
       // The operands have class type. Make a temporary copy.
+      if (RequireNonAbstractType(QuestionLoc, LTy,
+                                 diag::err_allocation_of_abstract_type))
+        return QualType();
       InitializedEntity Entity = InitializedEntity::InitializeTemporary(LTy);
+
       ExprResult LHSCopy = PerformCopyInitialization(Entity,
                                                      SourceLocation(),
                                                      LHS);
index a80eda416f4ebe90e0194f5ca7bd34042099eda5..7595f1dfa1c0008792522e72869893c1e4faaae9 100644 (file)
@@ -57,6 +57,16 @@ struct Ambig {
   operator signed char(); // expected-note 2 {{candidate function}}
 };
 
+struct Abstract {
+  virtual ~Abstract() = 0; // expected-note {{unimplemented pure virtual method '~Abstract' in 'Abstract'}}
+};
+
+struct Derived1: Abstract {
+};
+
+struct Derived2: Abstract {
+};
+
 void test()
 {
   // This function tests C++0x 5.16
@@ -206,6 +216,9 @@ void test()
   // Note the thing that this does not test: since DR446, various situations
   // *must* create a separate temporary copy of class objects. This can only
   // be properly tested at runtime, though.
+
+  const Abstract &a = true ? static_cast<const Abstract&>(Derived1()) : Derived2(); // expected-error {{allocating an object of abstract class type 'const Abstract'}}
+  true ? static_cast<const Abstract&>(Derived1()) : throw 3; // expected-error {{allocating an object of abstract class type 'const Abstract'}}
 }
 
 namespace PR6595 {