From: Douglas Gregor Date: Wed, 23 Dec 2009 20:51:04 +0000 (+0000) Subject: Remove cv-qualifiers from the argument to typeid X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f57f207a0fcf5fb7883597b57dd03faf952318dd;p=clang Remove cv-qualifiers from the argument to typeid git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@92041 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 45ee4fd64e..d395673e75 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/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/test/CodeGenCXX/rtti-linkage.cpp b/test/CodeGenCXX/rtti-linkage.cpp index 53209ed96c..11f328a1e4 100644 --- a/test/CodeGenCXX/rtti-linkage.cpp +++ b/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()); }