diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-05-17 01:46:05 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-05-17 01:46:05 +0000 |
commit | 7ee4307bd4450022c3c8777f43a40cc4f0ccc009 (patch) | |
tree | 15419c16f2805145912b9210e17268c957869de3 /clang/lib/AST/APValue.cpp | |
parent | 457d7caac82260adc5754d62f7133b178c7766be (diff) | |
download | bcm5719-llvm-7ee4307bd4450022c3c8777f43a40cc4f0ccc009.tar.gz bcm5719-llvm-7ee4307bd4450022c3c8777f43a40cc4f0ccc009.zip |
Refactor constant evaluation of typeid(T) to track a symbolic type_info
object rather than tracking the originating expression.
This is groundwork for supporting polymorphic typeid expressions. (Note
that this somewhat regresses our support for DR1968, but it turns out
that that never actually worked anyway, at least in non-trivial cases.)
llvm-svn: 360974
Diffstat (limited to 'clang/lib/AST/APValue.cpp')
-rw-r--r-- | clang/lib/AST/APValue.cpp | 59 |
1 files changed, 58 insertions, 1 deletions
diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp index e7902e68780..83b0fb5e1a2 100644 --- a/clang/lib/AST/APValue.cpp +++ b/clang/lib/AST/APValue.cpp @@ -20,6 +20,56 @@ #include "llvm/Support/raw_ostream.h" using namespace clang; +/// The identity of a type_info object depends on the canonical unqualified +/// type only. +TypeInfoLValue::TypeInfoLValue(const Type *T) + : T(T->getCanonicalTypeUnqualified().getTypePtr()) {} + +void TypeInfoLValue::print(llvm::raw_ostream &Out, + const PrintingPolicy &Policy) const { + Out << "typeid("; + QualType(getType(), 0).print(Out, Policy); + Out << ")"; +} + +static_assert( + 1 << llvm::PointerLikeTypeTraits<TypeInfoLValue>::NumLowBitsAvailable <= + alignof(const Type *), + "Type is insufficiently aligned"); + +APValue::LValueBase APValue::LValueBase::getTypeInfo(TypeInfoLValue LV, + QualType TypeInfo) { + LValueBase Base; + Base.Ptr = LV; + Base.TypeInfoType = TypeInfo.getAsOpaquePtr(); + return Base; +} + +unsigned APValue::LValueBase::getCallIndex() const { + return is<TypeInfoLValue>() ? 0 : Local.CallIndex; +} + +unsigned APValue::LValueBase::getVersion() const { + return is<TypeInfoLValue>() ? 0 : Local.Version; +} + +QualType APValue::LValueBase::getTypeInfoType() const { + assert(is<TypeInfoLValue>() && "not a type_info lvalue"); + return QualType::getFromOpaquePtr(TypeInfoType); +} + +namespace clang { +bool operator==(const APValue::LValueBase &LHS, + const APValue::LValueBase &RHS) { + if (LHS.Ptr != RHS.Ptr) + return false; + if (LHS.is<TypeInfoLValue>()) + return true; + return LHS.Local.CallIndex == RHS.Local.CallIndex && + LHS.Local.Version == RHS.Local.Version; +} +} + namespace { struct LVBase { APValue::LValueBase Base; @@ -60,6 +110,8 @@ llvm::DenseMapInfo<clang::APValue::LValueBase>::getTombstoneKey() { namespace clang { llvm::hash_code hash_value(const APValue::LValueBase &Base) { + if (Base.is<TypeInfoLValue>()) + return llvm::hash_value(Base.getOpaqueValue()); return llvm::hash_combine(Base.getOpaqueValue(), Base.getCallIndex(), Base.getVersion()); } @@ -470,7 +522,9 @@ void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{ if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) Out << *VD; - else { + else if (TypeInfoLValue TI = Base.dyn_cast<TypeInfoLValue>()) { + TI.print(Out, Ctx.getPrintingPolicy()); + } else { assert(Base.get<const Expr *>() != nullptr && "Expecting non-null Expr"); Base.get<const Expr*>()->printPretty(Out, nullptr, @@ -495,6 +549,9 @@ void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{ if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) { Out << *VD; ElemTy = VD->getType(); + } else if (TypeInfoLValue TI = Base.dyn_cast<TypeInfoLValue>()) { + TI.print(Out, Ctx.getPrintingPolicy()); + ElemTy = Base.getTypeInfoType(); } else { const Expr *E = Base.get<const Expr*>(); assert(E != nullptr && "Expecting non-null Expr"); |