From f45f6828c6d372fb5a203b874d205209a3aff2a7 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 23 Dec 2009 20:51:04 +0000 Subject: [PATCH] Remove cv-qualifiers from the argument to typeid llvm-svn: 92041 --- clang/lib/Sema/SemaExprCXX.cpp | 41 +++++++++++++++++++------- clang/test/CodeGenCXX/rtti-linkage.cpp | 11 ++++--- 2 files changed, 37 insertions(+), 15 deletions(-) diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 45ee4fd64e72..d395673e75bd 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -31,9 +31,14 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, if (!StdNamespace) return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid)); - if (isType) + if (isType) { + // C++ [expr.typeid]p4: + // The top-level cv-qualifiers of the lvalue expression or the type-id + // that is the operand of typeid are always ignored. // FIXME: Preserve type source info. - TyOrExpr = GetTypeFromParser(TyOrExpr).getAsOpaquePtr(); + // FIXME: Preserve the type before we stripped the cv-qualifiers? + TyOrExpr =GetTypeFromParser(TyOrExpr).getUnqualifiedType().getAsOpaquePtr(); + } IdentifierInfo *TypeInfoII = &PP.getIdentifierTable().get("type_info"); LookupResult R(*this, TypeInfoII, SourceLocation(), LookupTagName); @@ -45,21 +50,35 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, QualType TypeInfoType = Context.getTypeDeclType(TypeInfoRecordDecl); if (!isType) { - // C++0x [expr.typeid]p3: - // When typeid is applied to an expression other than an lvalue of a - // polymorphic class type [...] [the] expression is an unevaluated - // operand. - - // FIXME: if the type of the expression is a class type, the class - // shall be completely defined. bool isUnevaluatedOperand = true; Expr *E = static_cast(TyOrExpr); - if (E && !E->isTypeDependent() && E->isLvalue(Context) == Expr::LV_Valid) { + if (E && !E->isTypeDependent()) { QualType T = E->getType(); if (const RecordType *RecordT = T->getAs()) { CXXRecordDecl *RecordD = cast(RecordT->getDecl()); - if (RecordD->isPolymorphic()) + // C++ [expr.typeid]p3: + // When typeid is applied to an expression other than an lvalue of a + // polymorphic class type [...] [the] expression is an unevaluated + // operand. [...] + if (RecordD->isPolymorphic() && E->isLvalue(Context) == Expr::LV_Valid) isUnevaluatedOperand = false; + else { + // C++ [expr.typeid]p3: + // [...] If the type of the expression is a class type, the class + // shall be completely-defined. + // FIXME: implement this! + } + } + + // C++ [expr.typeid]p4: + // [...] If the type of the type-id is a reference to a possibly + // cv-qualified type, the result of the typeid expression refers to a + // std::type_info object representing the cv-unqualified referenced + // type. + if (T.hasQualifiers()) { + ImpCastExprToType(E, T.getUnqualifiedType(), CastExpr::CK_NoOp, + E->isLvalue(Context)); + TyOrExpr = E; } } diff --git a/clang/test/CodeGenCXX/rtti-linkage.cpp b/clang/test/CodeGenCXX/rtti-linkage.cpp index 53209ed96c78..11f328a1e48e 100644 --- a/clang/test/CodeGenCXX/rtti-linkage.cpp +++ b/clang/test/CodeGenCXX/rtti-linkage.cpp @@ -60,8 +60,11 @@ namespace { struct D { }; }; -void t2() { - (void)typeid(D); - (void)typeid(D *); - +const D getD(); + +const std::type_info &t2() { + (void)typeid(const D); + (void)typeid(D *); + // CHECK: _ZTIN12_GLOBAL__N_11DE to + return typeid(getD()); }