Canonicalize declaration pointers when forming APValues.

References to different declarations of the same entity aren't different
values, so shouldn't have different representations.

Recommit of e6393ee813, most recently
reverted in 9a33f027ac due to a bug caused
by ObjCInterfaceDecls not propagating availability attributes along
their redeclaration chains; that bug was fixed in
e2d4174e9c.
This commit is contained in:
Richard Smith 2020-09-02 14:42:37 -07:00
parent e2d4174e9c
commit 913f600566
9 changed files with 51 additions and 31 deletions

View File

@ -177,6 +177,7 @@ public:
return !(LHS == RHS);
}
friend llvm::hash_code hash_value(const LValueBase &Base);
friend struct llvm::DenseMapInfo<LValueBase>;
private:
PtrTy Ptr;
@ -204,8 +205,7 @@ public:
public:
LValuePathEntry() : Value() {}
LValuePathEntry(BaseOrMemberType BaseOrMember)
: Value{reinterpret_cast<uintptr_t>(BaseOrMember.getOpaqueValue())} {}
LValuePathEntry(BaseOrMemberType BaseOrMember);
static LValuePathEntry ArrayIndex(uint64_t Index) {
LValuePathEntry Result;
Result.Value = Index;

View File

@ -38,7 +38,7 @@ static_assert(
"Type is insufficiently aligned");
APValue::LValueBase::LValueBase(const ValueDecl *P, unsigned I, unsigned V)
: Ptr(P), Local{I, V} {}
: Ptr(P ? cast<ValueDecl>(P->getCanonicalDecl()) : nullptr), Local{I, V} {}
APValue::LValueBase::LValueBase(const Expr *P, unsigned I, unsigned V)
: Ptr(P), Local{I, V} {}
@ -90,13 +90,19 @@ bool operator==(const APValue::LValueBase &LHS,
const APValue::LValueBase &RHS) {
if (LHS.Ptr != RHS.Ptr)
return false;
if (LHS.is<TypeInfoLValue>())
if (LHS.is<TypeInfoLValue>() || LHS.is<DynamicAllocLValue>())
return true;
return LHS.Local.CallIndex == RHS.Local.CallIndex &&
LHS.Local.Version == RHS.Local.Version;
}
}
APValue::LValuePathEntry::LValuePathEntry(BaseOrMemberType BaseOrMember) {
if (const Decl *D = BaseOrMember.getPointer())
BaseOrMember.setPointer(D->getCanonicalDecl());
Value = reinterpret_cast<uintptr_t>(BaseOrMember.getOpaqueValue());
}
void APValue::LValuePathEntry::profile(llvm::FoldingSetNodeID &ID) const {
ID.AddInteger(Value);
}
@ -125,14 +131,16 @@ APValue::LValueBase::operator bool () const {
clang::APValue::LValueBase
llvm::DenseMapInfo<clang::APValue::LValueBase>::getEmptyKey() {
return clang::APValue::LValueBase(
DenseMapInfo<const ValueDecl*>::getEmptyKey());
clang::APValue::LValueBase B;
B.Ptr = DenseMapInfo<const ValueDecl*>::getEmptyKey();
return B;
}
clang::APValue::LValueBase
llvm::DenseMapInfo<clang::APValue::LValueBase>::getTombstoneKey() {
return clang::APValue::LValueBase(
DenseMapInfo<const ValueDecl*>::getTombstoneKey());
clang::APValue::LValueBase B;
B.Ptr = DenseMapInfo<const ValueDecl*>::getTombstoneKey();
return B;
}
namespace clang {
@ -926,8 +934,10 @@ void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
assert(isAbsent() && "Bad state change");
MemberPointerData *MPD = new ((void*)(char*)Data.buffer) MemberPointerData;
Kind = MemberPointer;
MPD->MemberAndIsDerivedMember.setPointer(Member);
MPD->MemberAndIsDerivedMember.setPointer(
Member ? cast<ValueDecl>(Member->getCanonicalDecl()) : nullptr);
MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember);
MPD->resizePath(Path.size());
memcpy(MPD->getPath(), Path.data(), Path.size()*sizeof(const CXXRecordDecl*));
for (unsigned I = 0; I != Path.size(); ++I)
MPD->getPath()[I] = Path[I]->getCanonicalDecl();
}

View File

@ -4686,11 +4686,9 @@ char *Buffer = new (getASTContext(), 1) char[Name.size() + 1];
void ValueDecl::anchor() {}
bool ValueDecl::isWeak() const {
for (const auto *I : attrs())
if (isa<WeakAttr>(I) || isa<WeakRefAttr>(I))
return true;
return isWeakImported();
auto *MostRecent = getMostRecentDecl();
return MostRecent->hasAttr<WeakAttr>() ||
MostRecent->hasAttr<WeakRefAttr>() || isWeakImported();
}
void ImplicitParamDecl::anchor() {}

View File

@ -720,7 +720,7 @@ bool Decl::isWeakImported() const {
if (!canBeWeakImported(IsDefinition))
return false;
for (const auto *A : attrs()) {
for (const auto *A : getMostRecentDecl()->attrs()) {
if (isa<WeakImportAttr>(A))
return true;

View File

@ -1982,18 +1982,11 @@ static bool HasSameBase(const LValue &A, const LValue &B) {
return false;
if (A.getLValueBase().getOpaqueValue() !=
B.getLValueBase().getOpaqueValue()) {
const Decl *ADecl = GetLValueBaseDecl(A);
if (!ADecl)
return false;
const Decl *BDecl = GetLValueBaseDecl(B);
if (!BDecl || ADecl->getCanonicalDecl() != BDecl->getCanonicalDecl())
return false;
}
B.getLValueBase().getOpaqueValue())
return false;
return IsGlobalLValue(A.getLValueBase()) ||
(A.getLValueCallIndex() == B.getLValueCallIndex() &&
A.getLValueVersion() == B.getLValueVersion());
return A.getLValueCallIndex() == B.getLValueCallIndex() &&
A.getLValueVersion() == B.getLValueVersion();
}
static void NoteLValueLocation(EvalInfo &Info, APValue::LValueBase Base) {
@ -3163,7 +3156,8 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
// If we're currently evaluating the initializer of this declaration, use that
// in-flight value.
if (Info.EvaluatingDecl.dyn_cast<const ValueDecl*>() == VD) {
if (declaresSameEntity(Info.EvaluatingDecl.dyn_cast<const ValueDecl *>(),
VD)) {
Result = Info.EvaluatingDeclValue;
return true;
}

View File

@ -1877,6 +1877,10 @@ ConstantLValue
ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) {
// Handle values.
if (const ValueDecl *D = base.dyn_cast<const ValueDecl*>()) {
// The constant always points to the canonical declaration. We want to look
// at properties of the most recent declaration at the point of emission.
D = cast<ValueDecl>(D->getMostRecentDecl());
if (D->hasAttr<WeakRefAttr>())
return CGM.GetWeakRefReference(D).getPointer();

View File

@ -24,11 +24,10 @@ constexpr double &ni3; // expected-error {{declaration of reference variable 'ni
constexpr int nc1 = i; // expected-error {{constexpr variable 'nc1' must be initialized by a constant expression}} expected-note {{read of non-const variable 'i' is not allowed in a constant expression}}
constexpr C nc2 = C(); // expected-error {{cannot have non-literal type 'const C'}}
int &f(); // expected-note {{declared here}}
int &f(); // expected-note 2{{declared here}}
constexpr int &nc3 = f(); // expected-error {{constexpr variable 'nc3' must be initialized by a constant expression}} expected-note {{non-constexpr function 'f' cannot be used in a constant expression}}
constexpr int nc4(i); // expected-error {{constexpr variable 'nc4' must be initialized by a constant expression}} expected-note {{read of non-const variable 'i' is not allowed in a constant expression}}
constexpr C nc5((C())); // expected-error {{cannot have non-literal type 'const C'}}
int &f(); // expected-note {{here}}
constexpr int &nc6(f()); // expected-error {{constexpr variable 'nc6' must be initialized by a constant expression}} expected-note {{non-constexpr function 'f'}}
struct pixel {

View File

@ -64,3 +64,15 @@ public:
void dummysymbol() {
throw(std::runtime_error("string"));
}
namespace not_weak_on_first {
int func();
// CHECK: {{.*}} extern_weak {{.*}} @_ZN17not_weak_on_first4funcEv(
int func() __attribute__ ((weak));
typedef int (*FuncT)();
extern const FuncT table[] = {
func,
};
}

View File

@ -16,6 +16,9 @@ void xxx(int argc) {
}
int foo();
#if __cplusplus >= 201103L
// expected-note@-2 {{declared here}}
#endif
template <class T>
T foo() {
@ -176,7 +179,7 @@ T foo() {
int foo() {
#if __cplusplus >= 201103L
// expected-note@-2 2 {{declared here}}
// expected-note@-2 {{declared here}}
#endif
int k;
#pragma omp for ordered