[cfe-commits] r67643 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDecl.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp test/Sema/function.c test/Sema/typecheck-binop.c test/SemaCXX/member-pointer.cpp test/SemaCXX/new-delete.cpp test/SemaTemplate/instantiate-complete.cpp

Douglas Gregor dgregor at apple.com
Tue Mar 24 12:52:55 PDT 2009


Author: dgregor
Date: Tue Mar 24 14:52:54 2009
New Revision: 67643

URL: http://llvm.org/viewvc/llvm-project?rev=67643&view=rev
Log:
Make sure to use RequireCompleteType rather than testing for
incomplete types. RequireCompleteType is needed when the type may be
completed by instantiating a template.

Added:
    cfe/trunk/test/SemaTemplate/instantiate-complete.cpp
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/test/Sema/function.c
    cfe/trunk/test/Sema/typecheck-binop.c
    cfe/trunk/test/SemaCXX/member-pointer.cpp
    cfe/trunk/test/SemaCXX/new-delete.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=67643&r1=67642&r2=67643&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Mar 24 14:52:54 2009
@@ -817,7 +817,7 @@
 def err_block_with_return_type_requires_args : Error<
   "block with explicit return type requires argument list">;
 def err_func_def_incomplete_result : Error<
-  "result type for function definition cannot be incomplete">;
+  "incomplete result type %0 in function definition">;
 
 // Expressions.
 def ext_sizeof_function_type : Extension<
@@ -842,8 +842,10 @@
 def err_typecheck_subscript_value : Error<
   "subscripted value is neither array nor pointer">;
 def err_typecheck_subscript : Error<"array subscript is not an integer">;
-def err_typecheck_subscript_not_object : Error<
-  "illegal subscript of non-object type %0">;
+def err_subscript_function_type : Error<
+  "subscript of pointer to function type %0">;
+def err_subscript_incomplete_type : Error<
+  "subscript of pointer to incomplete type %0">;
 def err_typecheck_member_reference_struct_union : Error<
   "member reference base type %0 is not a structure or union">;
 def err_typecheck_member_reference_ivar : Error<
@@ -1026,7 +1028,9 @@
 def err_array_new_needs_size : Error<
   "array size must be specified in new expressions">;
 def err_bad_new_type : Error<
-  "cannot allocate %select{function|incomplete|reference}1 type %0 with new">;
+  "cannot allocate %select{function|reference}1 type %0 with new">;
+def err_new_incomplete_type : Error<
+  "allocation of incomplete type %0">;
 def err_new_array_nonconst : Error<
   "only the first dimension of an allocated array may be non-const">;
 def err_array_size_not_integral : Error<
@@ -1049,8 +1053,9 @@
   "exception declarator cannot be qualified">;
 def err_early_catch_all : Error<"catch-all handler must come last">;
 def err_bad_memptr_rhs : Error<
-  "right hand operand to %0 must be a pointer to member of a complete class "
-  "but is %1">;
+  "right hand operand to %0 has non pointer-to-member type %1">;
+def err_memptr_rhs_incomplete : Error<
+  "right hand operand is a pointer to member of incomplete type %0">;
 
 def err_bad_memptr_lhs : Error<
   "left hand operand to %0 must be a %select{|pointer to }1class "

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=67643&r1=67642&r2=67643&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Mar 24 14:52:54 2009
@@ -881,6 +881,8 @@
     // C99 6.7.5.3p4: the parameters in a parameter type list in a
     // function declarator that is part of a function definition of
     // that function shall not have incomplete type.
+    //
+    // This is also C++ [dcl.fct]p6.
     if (!Param->isInvalidDecl() &&
         RequireCompleteType(Param->getLocation(), Param->getType(),
                                diag::err_typecheck_decl_incomplete_type)) {
@@ -2723,12 +2725,12 @@
   }
 
   // The return type of a function definition must be complete
-  // (C99 6.9.1p3)
-  if (FD->getResultType()->isIncompleteType() &&
-      !FD->getResultType()->isVoidType()) {
-    Diag(FD->getLocation(), diag::err_func_def_incomplete_result) << FD;
+  // (C99 6.9.1p3, C++ [dcl.fct]p6).
+  QualType ResultType = FD->getResultType();
+  if (!ResultType->isDependentType() && !ResultType->isVoidType() &&
+      RequireCompleteType(FD->getLocation(), ResultType,
+                          diag::err_func_def_incomplete_result))
     FD->setInvalidDecl();
-  }
 
   PushDeclContext(FnBodyScope, FD);
 
@@ -3726,33 +3728,27 @@
     if (FD->isInvalidDecl())
       continue;
       
-    // C99 6.7.2.1p2 - A field may not be a function type.
+    // C99 6.7.2.1p2:
+    //   A structure or union shall not contain a member with
+    //   incomplete or function type (hence, a structure shall not
+    //   contain an instance of itself, but may contain a pointer to
+    //   an instance of itself), except that the last member of a
+    //   structure with more than one named member may have incomplete
+    //   array type; such a structure (and any union containing,
+    //   possibly recursively, a member that is such a structure)
+    //   shall not be a member of a structure or an element of an
+    //   array.
     if (FDTy->isFunctionType()) {
+      // Field declared as a function.
       Diag(FD->getLocation(), diag::err_field_declared_as_function)
         << FD->getDeclName();
       FD->setInvalidDecl();
       EnclosingDecl->setInvalidDecl();
       continue;
-    }
-    // C99 6.7.2.1p2 - A field may not be an incomplete type except...
-    if (FDTy->isIncompleteType()) {
-      if (!Record) {  // Incomplete ivar type is always an error.
-        RequireCompleteType(FD->getLocation(), FD->getType(), 
-                               diag::err_field_incomplete);
-        FD->setInvalidDecl();
-        EnclosingDecl->setInvalidDecl();
-        continue;
-      }
-      if (i != NumFields-1 ||                   // ... that the last member ...
-          !Record->isStruct() ||  // ... of a structure ...
-          !FDTy->isArrayType()) {         //... may have incomplete array type.
-        RequireCompleteType(FD->getLocation(), FD->getType(), 
-                               diag::err_field_incomplete);
-        FD->setInvalidDecl();
-        EnclosingDecl->setInvalidDecl();
-        continue;
-      }
-      if (NumNamedMembers < 1) {  //... must have more than named member ...
+    } else if (FDTy->isIncompleteArrayType() && i == NumFields - 1 &&
+               Record && Record->isStruct()) {
+      // Flexible array member.
+      if (NumNamedMembers < 1) {
         Diag(FD->getLocation(), diag::err_flexible_array_empty_struct)
           << FD->getDeclName();
         FD->setInvalidDecl();
@@ -3762,10 +3758,14 @@
       // Okay, we have a legal flexible array member at the end of the struct.
       if (Record)
         Record->setHasFlexibleArrayMember(true);
-    }
-    /// C99 6.7.2.1p2 - a struct ending in a flexible array member cannot be the
-    /// field of another structure or the element of an array.
-    if (const RecordType *FDTTy = FDTy->getAsRecordType()) {
+    } else if (!FDTy->isDependentType() &&
+               RequireCompleteType(FD->getLocation(), FD->getType(), 
+                                   diag::err_field_incomplete)) {
+      // Incomplete type
+      FD->setInvalidDecl();
+      EnclosingDecl->setInvalidDecl();
+      continue;
+    } else if (const RecordType *FDTTy = FDTy->getAsRecordType()) {
       if (FDTTy->getDecl()->hasFlexibleArrayMember()) {
         // If this is a member of a union, then entire union becomes "flexible".
         if (Record && Record->isUnion()) {
@@ -3787,9 +3787,8 @@
           }
         }
       }
-    }
-    /// A field cannot be an Objective-c object
-    if (FDTy->isObjCInterfaceType()) {
+    } else if (FDTy->isObjCInterfaceType()) {
+      /// A field cannot be an Objective-c object
       Diag(FD->getLocation(), diag::err_statically_allocated_object);
       FD->setInvalidDecl();
       EnclosingDecl->setInvalidDecl();

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=67643&r1=67642&r2=67643&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Mar 24 14:52:54 2009
@@ -1593,14 +1593,20 @@
     return ExprError(Diag(IndexExpr->getLocStart(),
       diag::err_typecheck_subscript) << IndexExpr->getSourceRange());
 
-  // C99 6.5.2.1p1: "shall have type "pointer to *object* type".  In practice,
-  // the following check catches trying to index a pointer to a function (e.g.
-  // void (*)(int)) and pointers to incomplete types.  Functions are not
-  // objects in C99.
-  if (!ResultType->isObjectType() && !ResultType->isDependentType())
-    return ExprError(Diag(BaseExpr->getLocStart(),
-                diag::err_typecheck_subscript_not_object)
-      << BaseExpr->getType() << BaseExpr->getSourceRange());
+  // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
+  // C++ [expr.sub]p1: The type "T" shall be a completely-defined object 
+  // type. Note that Functions are not objects, and that (in C99 parlance) 
+  // incomplete types are not object types.
+  if (ResultType->isFunctionType()) {
+    Diag(BaseExpr->getLocStart(), diag::err_subscript_function_type)
+      << ResultType << BaseExpr->getSourceRange();
+    return ExprError();
+  }
+  if (!ResultType->isDependentType() &&
+      RequireCompleteType(BaseExpr->getLocStart(), ResultType, 
+                          diag::err_subscript_incomplete_type,
+                          BaseExpr->getSourceRange()))
+    return ExprError();
 
   Base.release();
   Idx.release();
@@ -3155,35 +3161,33 @@
   if (const PointerType* PTy = PExp->getType()->getAsPointerType()) {
     if (IExp->getType()->isIntegerType()) {
       // Check for arithmetic on pointers to incomplete types
-      if (!PTy->getPointeeType()->isObjectType()) {
-        if (PTy->getPointeeType()->isVoidType()) {
-          if (getLangOptions().CPlusPlus) {
-            Diag(Loc, diag::err_typecheck_pointer_arith_void_type)
-              << lex->getSourceRange() << rex->getSourceRange();
-            return QualType();
-          }
-
-          // GNU extension: arithmetic on pointer to void
-          Diag(Loc, diag::ext_gnu_void_ptr)
+      if (PTy->getPointeeType()->isVoidType()) {
+        if (getLangOptions().CPlusPlus) {
+          Diag(Loc, diag::err_typecheck_pointer_arith_void_type)
             << lex->getSourceRange() << rex->getSourceRange();
-        } else if (PTy->getPointeeType()->isFunctionType()) {
-          if (getLangOptions().CPlusPlus) {
-            Diag(Loc, diag::err_typecheck_pointer_arith_function_type)
-              << lex->getType() << lex->getSourceRange();
-            return QualType();
-          }
+          return QualType();
+        }
 
-          // GNU extension: arithmetic on pointer to function
-          Diag(Loc, diag::ext_gnu_ptr_func_arith)
+        // GNU extension: arithmetic on pointer to void
+        Diag(Loc, diag::ext_gnu_void_ptr)
+          << lex->getSourceRange() << rex->getSourceRange();
+      } else if (PTy->getPointeeType()->isFunctionType()) {
+        if (getLangOptions().CPlusPlus) {
+          Diag(Loc, diag::err_typecheck_pointer_arith_function_type)
             << lex->getType() << lex->getSourceRange();
-        } else {
-          RequireCompleteType(Loc, PTy->getPointeeType(),
-                                 diag::err_typecheck_arithmetic_incomplete_type,
-                                 lex->getSourceRange(), SourceRange(),
-                                 lex->getType());
           return QualType();
         }
-      }
+
+        // GNU extension: arithmetic on pointer to function
+        Diag(Loc, diag::ext_gnu_ptr_func_arith)
+          << lex->getType() << lex->getSourceRange();
+      } else if (!PTy->isDependentType() &&
+                 RequireCompleteType(Loc, PTy->getPointeeType(),
+                                diag::err_typecheck_arithmetic_incomplete_type,
+                                     lex->getSourceRange(), SourceRange(),
+                                     lex->getType()))
+        return QualType();
+
       return PExp->getType();
     }
   }
@@ -3209,61 +3213,80 @@
   if (const PointerType *LHSPTy = lex->getType()->getAsPointerType()) {
     QualType lpointee = LHSPTy->getPointeeType();
 
-    // The LHS must be an object type, not incomplete, function, etc.
-    if (!lpointee->isObjectType()) {
-      // Handle the GNU void* extension.
-      if (lpointee->isVoidType()) {
-        Diag(Loc, diag::ext_gnu_void_ptr)
+    // The LHS must be an completely-defined object type.
+
+    bool ComplainAboutVoid = false;
+    Expr *ComplainAboutFunc = 0;
+    if (lpointee->isVoidType()) {
+      if (getLangOptions().CPlusPlus) {
+        Diag(Loc, diag::err_typecheck_pointer_arith_void_type)
           << lex->getSourceRange() << rex->getSourceRange();
-      } else if (lpointee->isFunctionType()) {
-        if (getLangOptions().CPlusPlus) {
-          Diag(Loc, diag::err_typecheck_pointer_arith_function_type)
-            << lex->getType() << lex->getSourceRange();
-          return QualType();
-        }
+        return QualType();
+      }
 
-        // GNU extension: arithmetic on pointer to function
-        Diag(Loc, diag::ext_gnu_ptr_func_arith)
-          << lex->getType() << lex->getSourceRange();
-      } else {
-        Diag(Loc, diag::err_typecheck_sub_ptr_object)
+      // GNU C extension: arithmetic on pointer to void
+      ComplainAboutVoid = true;
+    } else if (lpointee->isFunctionType()) {
+      if (getLangOptions().CPlusPlus) {
+        Diag(Loc, diag::err_typecheck_pointer_arith_function_type)
           << lex->getType() << lex->getSourceRange();
         return QualType();
       }
-    }
+
+      // GNU C extension: arithmetic on pointer to function
+      ComplainAboutFunc = lex;
+    } else if (!lpointee->isDependentType() &&
+               RequireCompleteType(Loc, lpointee, 
+                                   diag::err_typecheck_sub_ptr_object,
+                                   lex->getSourceRange(),
+                                   SourceRange(),
+                                   lex->getType()))
+      return QualType();
 
     // The result type of a pointer-int computation is the pointer type.
-    if (rex->getType()->isIntegerType())
+    if (rex->getType()->isIntegerType()) {
+      if (ComplainAboutVoid)
+        Diag(Loc, diag::ext_gnu_void_ptr)
+          << lex->getSourceRange() << rex->getSourceRange();
+      if (ComplainAboutFunc)
+        Diag(Loc, diag::ext_gnu_ptr_func_arith)
+          << ComplainAboutFunc->getType() 
+          << ComplainAboutFunc->getSourceRange();
+
       return lex->getType();
+    }
 
     // Handle pointer-pointer subtractions.
     if (const PointerType *RHSPTy = rex->getType()->getAsPointerType()) {
       QualType rpointee = RHSPTy->getPointeeType();
 
-      // RHS must be an object type, unless void (GNU).
-      if (!rpointee->isObjectType()) {
-        // Handle the GNU void* extension.
-        if (rpointee->isVoidType()) {
-          if (!lpointee->isVoidType())
-            Diag(Loc, diag::ext_gnu_void_ptr)
-              << lex->getSourceRange() << rex->getSourceRange();
-        } else if (rpointee->isFunctionType()) {
-          if (getLangOptions().CPlusPlus) {
-            Diag(Loc, diag::err_typecheck_pointer_arith_function_type)
-              << rex->getType() << rex->getSourceRange();
-            return QualType();
-          }
-
-          // GNU extension: arithmetic on pointer to function
-          if (!lpointee->isFunctionType())
-            Diag(Loc, diag::ext_gnu_ptr_func_arith)
-              << lex->getType() << lex->getSourceRange();
-        } else {
-          Diag(Loc, diag::err_typecheck_sub_ptr_object)
+      // RHS must be a completely-type object type.
+      // Handle the GNU void* extension.
+      if (rpointee->isVoidType()) {
+        if (getLangOptions().CPlusPlus) {
+          Diag(Loc, diag::err_typecheck_pointer_arith_void_type)
+            << lex->getSourceRange() << rex->getSourceRange();
+          return QualType();
+        }
+
+        ComplainAboutVoid = true;
+      } else if (rpointee->isFunctionType()) {
+        if (getLangOptions().CPlusPlus) {
+          Diag(Loc, diag::err_typecheck_pointer_arith_function_type)
             << rex->getType() << rex->getSourceRange();
           return QualType();
         }
-      }
+
+        // GNU extension: arithmetic on pointer to function
+        if (!ComplainAboutFunc)
+          ComplainAboutFunc = rex;
+      } else if (!rpointee->isDependentType() &&
+                 RequireCompleteType(Loc, rpointee,
+                                     diag::err_typecheck_sub_ptr_object,
+                                     rex->getSourceRange(),
+                                     SourceRange(),
+                                     rex->getType()))
+        return QualType();
 
       // Pointee types must be compatible.
       if (!Context.typesAreCompatible(
@@ -3275,6 +3298,14 @@
         return QualType();
       }
 
+      if (ComplainAboutVoid)
+        Diag(Loc, diag::ext_gnu_void_ptr)
+          << lex->getSourceRange() << rex->getSourceRange();
+      if (ComplainAboutFunc)
+        Diag(Loc, diag::ext_gnu_ptr_func_arith)
+          << ComplainAboutFunc->getType() 
+          << ComplainAboutFunc->getSourceRange();
+        
       return Context.getPointerDiffType();
     }
   }

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=67643&r1=67642&r2=67643&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Mar 24 14:52:54 2009
@@ -242,10 +242,6 @@
   if (CheckAllocatedType(AllocType, D))
     return ExprError();
 
-  if (RequireNonAbstractType(D.getSourceRange().getBegin(), AllocType,
-                             diag::err_allocation_of_abstract_type))
-    return ExprError();
-  
   QualType ResultType = AllocType->isDependentType()
                           ? Context.DependentTy
                           : Context.getPointerType(AllocType);
@@ -364,23 +360,20 @@
 {
   // C++ 5.3.4p1: "[The] type shall be a complete object type, but not an
   //   abstract class type or array thereof.
-  // FIXME: We don't have abstract types yet.
-  // FIXME: Under C++ semantics, an incomplete object type is still an object
-  // type. This code assumes the C semantics, where it's not.
-  if (!AllocType->isObjectType()) {
-    unsigned type; // For the select in the message.
-    if (AllocType->isFunctionType()) {
-      type = 0;
-    } else if(AllocType->isIncompleteType()) {
-      type = 1;
-    } else {
-      assert(AllocType->isReferenceType() && "Unhandled non-object type.");
-      type = 2;
-    }
-    Diag(D.getSourceRange().getBegin(), diag::err_bad_new_type)
-      << AllocType << type << D.getSourceRange();
+  if (AllocType->isFunctionType())
+    return Diag(D.getSourceRange().getBegin(), diag::err_bad_new_type)
+      << AllocType << 0 << D.getSourceRange();
+  else if (AllocType->isReferenceType())
+    return Diag(D.getSourceRange().getBegin(), diag::err_bad_new_type)
+      << AllocType << 1 << D.getSourceRange();
+  else if (!AllocType->isDependentType() &&
+           RequireCompleteType(D.getSourceRange().getBegin(), AllocType,
+                               diag::err_new_incomplete_type,
+                               D.getSourceRange()))
+    return true;
+  else if (RequireNonAbstractType(D.getSourceRange().getBegin(), AllocType,
+                                  diag::err_allocation_of_abstract_type))
     return true;
-  }
 
   // Every dimension shall be of constant size.
   unsigned i = 1;
@@ -943,11 +936,15 @@
   //   class type) [...]
   QualType RType = rex->getType();
   const MemberPointerType *MemPtr = RType->getAsMemberPointerType();
-  if (!MemPtr || MemPtr->getClass()->isIncompleteType()) {
+  if (!MemPtr) {
     Diag(Loc, diag::err_bad_memptr_rhs)
       << OpSpelling << RType << rex->getSourceRange();
     return QualType();
-  }
+  } else if (RequireCompleteType(Loc, QualType(MemPtr->getClass(), 0),
+                                 diag::err_memptr_rhs_incomplete,
+                                 rex->getSourceRange()))
+    return QualType();
+
   QualType Class(MemPtr->getClass(), 0);
 
   // C++ 5.5p2

Modified: cfe/trunk/test/Sema/function.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/function.c?rev=67643&r1=67642&r2=67643&view=diff

==============================================================================
--- cfe/trunk/test/Sema/function.c (original)
+++ cfe/trunk/test/Sema/function.c Tue Mar 24 14:52:54 2009
@@ -59,4 +59,5 @@
   register void f2register(int); // expected-error{{illegal storage class on function}}
 }
 
-struct incomplete_test a(void) {} // expected-error{{result type for function definition cannot be incomplete}}
+struct incomplete_test a(void) {} // expected-error{{incomplete result type 'struct incomplete_test' in function definition}} \
+    // expected-note{{forward declaration of 'struct incomplete_test'}}

Modified: cfe/trunk/test/Sema/typecheck-binop.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/typecheck-binop.c?rev=67643&r1=67642&r2=67643&view=diff

==============================================================================
--- cfe/trunk/test/Sema/typecheck-binop.c (original)
+++ cfe/trunk/test/Sema/typecheck-binop.c Tue Mar 24 14:52:54 2009
@@ -1,6 +1,6 @@
 /* RUN: clang-cc %s -fsyntax-only -pedantic -verify
  */
-struct incomplete;
+struct incomplete; // expected-note{{forward declaration of 'struct incomplete'}}
 
 int sub1(int *a, double *b) { 
   return a - b;    /* expected-error{{not pointers to compatible types}} */
@@ -18,6 +18,10 @@
   return P-Q;      /* expected-warning{{GNU void* extension}} */
 }
 
+int sub5(void *P, int *Q) {
+  return P-Q;      /* expected-error{{not pointers to compatible types}} */
+}
+
 int logicaland1(int a) {
   return a && (void)a; /* expected-error{{invalid operands}} */
 }

Modified: cfe/trunk/test/SemaCXX/member-pointer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/member-pointer.cpp?rev=67643&r1=67642&r2=67643&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/member-pointer.cpp (original)
+++ cfe/trunk/test/SemaCXX/member-pointer.cpp Tue Mar 24 14:52:54 2009
@@ -80,7 +80,7 @@
   void (HasMembers::*pmd)() = &HasMembers::d;
 }
 
-struct Incomplete;
+struct Incomplete; // expected-note{{forward declaration}}
 
 void h() {
   HasMembers hm, *phm = &hm;
@@ -110,12 +110,12 @@
   (void)(f.*pai); // expected-error {{left hand operand to .* must be a class compatible with the right hand operand, but is 'struct F'}}
   (void)(ptrf->*pai); // expected-error {{left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'struct F *'}}
 
-  (void)(hm.*i); // expected-error {{right hand operand to .* must be a pointer to member of a complete class but is 'int'}}
-  (void)(phm->*i); // expected-error {{right hand operand to ->* must be a pointer to member of a complete class but is 'int'}}
+  (void)(hm.*i); // expected-error {{pointer-to-member}}
+  (void)(phm->*i); // expected-error {{pointer-to-member}}
 
   Incomplete *inc;
   int Incomplete::*pii = 0;
-  (void)inc->*pii; // expected-error {{right hand operand to ->* must be a pointer to member of a complete class but is 'int struct Incomplete::*'}}
+  (void)inc->*pii; // expected-error {{right hand operand is a pointer to member of incomplete type 'struct Incomplete'}}
 }
 
 struct OverloadsPtrMem

Modified: cfe/trunk/test/SemaCXX/new-delete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/new-delete.cpp?rev=67643&r1=67642&r2=67643&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/new-delete.cpp (original)
+++ cfe/trunk/test/SemaCXX/new-delete.cpp Tue Mar 24 14:52:54 2009
@@ -41,6 +41,10 @@
   //V *pv = new (ps) V;
 }
 
+struct abstract {
+  virtual ~abstract() = 0;
+};
+
 void bad_news(int *ip)
 {
   int i = 1;
@@ -66,7 +70,6 @@
   (void)::new ((S*)0) U; // expected-error {{no matching function for call to 'operator new'}}
   (void)new (int[]); // expected-error {{array size must be specified in new expressions}}
   (void)new int&; // expected-error {{cannot allocate reference type 'int &' with new}}
-  (void)new (void ()); // expected-error {{cannot allocate function type 'void (void)' with new}}
   // Some lacking cases due to lack of sema support.
 }
 

Added: cfe/trunk/test/SemaTemplate/instantiate-complete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-complete.cpp?rev=67643&view=auto

==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-complete.cpp (added)
+++ cfe/trunk/test/SemaTemplate/instantiate-complete.cpp Tue Mar 24 14:52:54 2009
@@ -0,0 +1,47 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// Tests various places where requiring a complete type involves
+// instantiation of that type.
+
+template<typename T>
+struct X {
+  X(T);
+
+  T f; // expected-error{{data member instantiated with function type 'float (int)'}} \
+       // expected-error{{data member instantiated with function type 'int (int)'}} \
+       // expected-error{{data member instantiated with function type 'char (char)'}} \
+       // expected-error{{data member instantiated with function type 'short (short)'}} \
+       // expected-error{{data member instantiated with function type 'float (float)'}} \
+       // expected-error{{data member instantiated with function type 'long (long)'}}
+};
+
+X<int> f() { return 0; }
+
+struct XField {
+  X<float(int)> xf; // expected-note{{in instantiation of template class 'struct X<float (int)>' requested here}}
+};
+
+void test_subscript(X<double> *ptr1, X<int(int)> *ptr2, int i) {
+  (void)ptr1[i];
+  (void)ptr2[i]; // expected-note{{in instantiation of template class 'struct X<int (int)>' requested here}}
+}
+
+void test_arith(X<signed char> *ptr1, X<unsigned char> *ptr2,
+                X<char(char)> *ptr3, X<short(short)> *ptr4) {
+  (void)(ptr1 + 5);
+  // FIXME: if I drop the ')' after void, below, it still parses (!)
+  (void)(5 + ptr2);
+  (void)(ptr3 + 5); // expected-note{{in instantiation of template class 'struct X<char (char)>' requested here}}
+  (void)(5 + ptr4); // expected-note{{in instantiation of template class 'struct X<short (short)>' requested here}}
+}
+
+void test_new() {
+  (void)new X<float>(0);
+  (void)new X<float(float)>; // expected-note{{in instantiation of template class 'struct X<float (float)>' requested here}}
+}
+
+void test_memptr(X<long> *p1, long X<long>::*pm1,
+                 X<long(long)> *p2, long (X<long(long)>::*pm2)(long)) {
+  (void)(p1->*pm1);
+  (void)(p2->*pm2); // expected-note{{in instantiation of template class 'struct X<long (long)>' requested here}}
+}





More information about the cfe-commits mailing list