]> granicus.if.org Git - clang/commitdiff
Diagnose the use of incomplete types in C++ typeid expressions
authorDouglas Gregor <dgregor@apple.com>
Wed, 23 Dec 2009 21:06:06 +0000 (21:06 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 23 Dec 2009 21:06:06 +0000 (21:06 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@92045 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaExprCXX.cpp
test/SemaCXX/typeid.cpp
test/SemaTemplate/instantiate-expr-4.cpp

index cd6f6894d9029ec50854023b1391412fb6684571..6f1039e9786eff5eb43c8944d84301f85d272cc2 100644 (file)
@@ -1830,6 +1830,7 @@ def err_bad_dynamic_cast_not_polymorphic : Error<"%0 is not polymorphic">;
 // Other C++ expressions
 def err_need_header_before_typeid : Error<
   "you need to include <typeinfo> before using the 'typeid' operator">;
+def err_incomplete_typeid : Error<"'typeid' of incomplete type %0">;
 def err_static_illegal_in_new : Error<
   "the 'static' modifier for the array size is not legal in new expressions">;
 def err_array_new_needs_size : Error<
index d395673e75bd65c7681d926178a12f8f29f63786..afb5c54d65c796a9c4632e56a82a445352d19178 100644 (file)
@@ -37,7 +37,22 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
     //   that is the operand of typeid are always ignored.
     // FIXME: Preserve type source info.
     // FIXME: Preserve the type before we stripped the cv-qualifiers?
-    TyOrExpr =GetTypeFromParser(TyOrExpr).getUnqualifiedType().getAsOpaquePtr();
+    QualType T = GetTypeFromParser(TyOrExpr);
+    if (T.isNull())
+      return ExprError();
+    
+    // C++ [expr.typeid]p4:
+    //   If the type of the type-id is a class type or a reference to a class 
+    //   type, the class shall be completely-defined.
+    QualType CheckT = T;
+    if (const ReferenceType *RefType = CheckT->getAs<ReferenceType>())
+      CheckT = RefType->getPointeeType();
+    
+    if (CheckT->getAs<RecordType>() &&
+        RequireCompleteType(OpLoc, CheckT, diag::err_incomplete_typeid))
+      return ExprError();
+    
+    TyOrExpr = T.getUnqualifiedType().getAsOpaquePtr();
   }
 
   IdentifierInfo *TypeInfoII = &PP.getIdentifierTable().get("type_info");
@@ -66,7 +81,8 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
           // C++ [expr.typeid]p3:
           //   [...] If the type of the expression is a class type, the class
           //   shall be completely-defined.
-          // FIXME: implement this!
+          if (RequireCompleteType(OpLoc, T, diag::err_incomplete_typeid))
+            return ExprError();
         }
       }
 
index 43403105759896867e6b6bae21d4da205dc003a0..7960cac783103435919b34401441182d4018a6b1 100644 (file)
@@ -14,3 +14,11 @@ void g()
 {
   (void)typeid(int);
 }
+
+struct X; // expected-note 3{{forward declaration}}
+
+void g1(X &x) {
+  (void)typeid(X); // expected-error{{'typeid' of incomplete type 'struct X'}}
+  (void)typeid(X&); // expected-error{{'typeid' of incomplete type 'struct X'}}
+  (void)typeid(x); // expected-error{{'typeid' of incomplete type 'struct X'}}
+}
index 99bbbf7a162c0f8229e65d0264453a770287af87..c524e958f8a7747c5447b2cd6993b85775ce38ba 100644 (file)
@@ -133,7 +133,7 @@ struct Throw1 {
   }
 };
 
-struct Incomplete; // expected-note{{forward}}
+struct Incomplete; // expected-note 2{{forward}}
 
 template struct Throw1<int>;
 template struct Throw1<int*>;
@@ -143,7 +143,6 @@ template struct Throw1<Incomplete*>; // expected-note{{instantiation}}
 // typeid expressions
 // ---------------------------------------------------------------------
 
-// FIXME: This should really include <typeinfo>, but we don't have that yet.
 namespace std {
   class type_info;
 }
@@ -154,7 +153,7 @@ struct TypeId0 {
     if (ptr)
       return typeid(ptr);
     else
-      return typeid(T);
+      return typeid(T); // expected-error{{'typeid' of incomplete type 'struct Incomplete'}}
   }
 };
 
@@ -163,7 +162,7 @@ struct Abstract {
 };
 
 template struct TypeId0<int>;
-template struct TypeId0<Incomplete>;
+template struct TypeId0<Incomplete>; // expected-note{{instantiation of member function}}
 template struct TypeId0<Abstract>;
 
 // ---------------------------------------------------------------------