aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-12-23 21:06:06 +0000
committerDouglas Gregor <dgregor@apple.com>2009-12-23 21:06:06 +0000
commit765ccba920269eefbf572ec4bcd6ac7b6e9f9f77 (patch)
tree6afe94d058d9f1cc9e269baabf8c832a6c185318
parent520ad5f7bcbf66a9ef2f6b25e719cbdbcc5534f3 (diff)
Diagnose the use of incomplete types in C++ typeid expressions
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@92045 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td1
-rw-r--r--lib/Sema/SemaExprCXX.cpp20
-rw-r--r--test/SemaCXX/typeid.cpp8
-rw-r--r--test/SemaTemplate/instantiate-expr-4.cpp7
4 files changed, 30 insertions, 6 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index cd6f6894d9..6f1039e978 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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<
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index d395673e75..afb5c54d65 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -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();
}
}
diff --git a/test/SemaCXX/typeid.cpp b/test/SemaCXX/typeid.cpp
index 4340310575..7960cac783 100644
--- a/test/SemaCXX/typeid.cpp
+++ b/test/SemaCXX/typeid.cpp
@@ -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'}}
+}
diff --git a/test/SemaTemplate/instantiate-expr-4.cpp b/test/SemaTemplate/instantiate-expr-4.cpp
index 99bbbf7a16..c524e958f8 100644
--- a/test/SemaTemplate/instantiate-expr-4.cpp
+++ b/test/SemaTemplate/instantiate-expr-4.cpp
@@ -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>;
// ---------------------------------------------------------------------