From: Richard Smith Date: Tue, 10 Nov 2020 20:51:00 +0000 (-0800) Subject: Move code to determine the type of an LValueBase out of ExprConstant and X-Git-Tag: llvmorg-13-init~6507 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=438a27f2e56a9753d4cc8477a1f1c306edc4c885;p=platform%2Fupstream%2Fllvm.git Move code to determine the type of an LValueBase out of ExprConstant and into a member function on LValueBase. NFC. --- diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h index 6cda588..4c063ca 100644 --- a/clang/include/clang/AST/APValue.h +++ b/clang/include/clang/AST/APValue.h @@ -173,6 +173,8 @@ public: QualType getTypeInfoType() const; QualType getDynamicAllocType() const; + QualType getType() const; + friend bool operator==(const LValueBase &LHS, const LValueBase &RHS); friend bool operator!=(const LValueBase &LHS, const LValueBase &RHS) { return !(LHS == RHS); diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp index e3fb015..266421c 100644 --- a/clang/lib/AST/APValue.cpp +++ b/clang/lib/AST/APValue.cpp @@ -60,6 +60,51 @@ APValue::LValueBase APValue::LValueBase::getTypeInfo(TypeInfoLValue LV, return Base; } +QualType APValue::LValueBase::getType() const { + if (!*this) return QualType(); + if (const ValueDecl *D = dyn_cast()) { + // FIXME: It's unclear where we're supposed to take the type from, and + // this actually matters for arrays of unknown bound. Eg: + // + // extern int arr[]; void f() { extern int arr[3]; }; + // constexpr int *p = &arr[1]; // valid? + // + // For now, we take the most complete type we can find. + for (auto *Redecl = cast(D->getMostRecentDecl()); Redecl; + Redecl = cast_or_null(Redecl->getPreviousDecl())) { + QualType T = Redecl->getType(); + if (!T->isIncompleteArrayType()) + return T; + } + return D->getType(); + } + + if (is()) + return getTypeInfoType(); + + if (is()) + return getDynamicAllocType(); + + const Expr *Base = get(); + + // For a materialized temporary, the type of the temporary we materialized + // may not be the type of the expression. + if (const MaterializeTemporaryExpr *MTE = + clang::dyn_cast(Base)) { + SmallVector CommaLHSs; + SmallVector Adjustments; + const Expr *Temp = MTE->getSubExpr(); + const Expr *Inner = Temp->skipRValueSubobjectAdjustments(CommaLHSs, + Adjustments); + // Keep any cv-qualifiers from the reference if we generated a temporary + // for it directly. Otherwise use the type after adjustment. + if (!Adjustments.empty()) + return Inner->getType(); + } + + return Base->getType(); +} + unsigned APValue::LValueBase::getCallIndex() const { return (is() || is()) ? 0 : Local.CallIndex; @@ -685,31 +730,25 @@ void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, else if (isLValueOnePastTheEnd()) Out << "*(&"; - QualType ElemTy; + QualType ElemTy = Base.getType(); if (const ValueDecl *VD = Base.dyn_cast()) { Out << *VD; - ElemTy = VD->getType(); } else if (TypeInfoLValue TI = Base.dyn_cast()) { TI.print(Out, Ctx.getPrintingPolicy()); - ElemTy = Base.getTypeInfoType(); } else if (DynamicAllocLValue DA = Base.dyn_cast()) { Out << "{*new " << Base.getDynamicAllocType().stream(Ctx.getPrintingPolicy()) << "#" << DA.getIndex() << "}"; - ElemTy = Base.getDynamicAllocType(); } else { const Expr *E = Base.get(); assert(E != nullptr && "Expecting non-null Expr"); E->printPretty(Out, nullptr, Ctx.getPrintingPolicy()); - // FIXME: This is wrong if E is a MaterializeTemporaryExpr with an lvalue - // adjustment. - ElemTy = E->getType(); } ArrayRef Path = getLValuePath(); const CXXRecordDecl *CastToBase = nullptr; for (unsigned I = 0, N = Path.size(); I != N; ++I) { - if (ElemTy->getAs()) { + if (ElemTy->isRecordType()) { // The lvalue refers to a class type, so the next path entry is a base // or member. const Decl *BaseOrMember = Path[I].getAsBaseOrMember().getPointer(); diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index b824470e..44560c6 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -79,48 +79,7 @@ namespace { CurrentSourceLocExprScope::SourceLocExprScopeGuard; static QualType getType(APValue::LValueBase B) { - if (!B) return QualType(); - if (const ValueDecl *D = B.dyn_cast()) { - // FIXME: It's unclear where we're supposed to take the type from, and - // this actually matters for arrays of unknown bound. Eg: - // - // extern int arr[]; void f() { extern int arr[3]; }; - // constexpr int *p = &arr[1]; // valid? - // - // For now, we take the array bound from the most recent declaration. - for (auto *Redecl = cast(D->getMostRecentDecl()); Redecl; - Redecl = cast_or_null(Redecl->getPreviousDecl())) { - QualType T = Redecl->getType(); - if (!T->isIncompleteArrayType()) - return T; - } - return D->getType(); - } - - if (B.is()) - return B.getTypeInfoType(); - - if (B.is()) - return B.getDynamicAllocType(); - - const Expr *Base = B.get(); - - // For a materialized temporary, the type of the temporary we materialized - // may not be the type of the expression. - if (const MaterializeTemporaryExpr *MTE = - dyn_cast(Base)) { - SmallVector CommaLHSs; - SmallVector Adjustments; - const Expr *Temp = MTE->getSubExpr(); - const Expr *Inner = Temp->skipRValueSubobjectAdjustments(CommaLHSs, - Adjustments); - // Keep any cv-qualifiers from the reference if we generated a temporary - // for it directly. Otherwise use the type after adjustment. - if (!Adjustments.empty()) - return Inner->getType(); - } - - return Base->getType(); + return B.getType(); } /// Get an LValue path entry, which is known to not be an array index, as a