diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-12-23 21:06:06 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-12-23 21:06:06 +0000 |
commit | 765ccba920269eefbf572ec4bcd6ac7b6e9f9f77 (patch) | |
tree | 6afe94d058d9f1cc9e269baabf8c832a6c185318 | |
parent | 520ad5f7bcbf66a9ef2f6b25e719cbdbcc5534f3 (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.td | 1 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 20 | ||||
-rw-r--r-- | test/SemaCXX/typeid.cpp | 8 | ||||
-rw-r--r-- | test/SemaTemplate/instantiate-expr-4.cpp | 7 |
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>; // --------------------------------------------------------------------- |