Skip to content

Commit

Permalink
Canonicalize declaration pointers when forming APValues.
Browse files Browse the repository at this point in the history
References to different declarations of the same entity aren't different
values, so shouldn't have different representations.
  • Loading branch information
zygoloid committed Sep 3, 2020
1 parent 3d54976 commit e6393ee
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 25 deletions.
4 changes: 2 additions & 2 deletions clang/include/clang/AST/APValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ class APValue {
return !(LHS == RHS);
}
friend llvm::hash_code hash_value(const LValueBase &Base);
friend struct llvm::DenseMapInfo<LValueBase>;

private:
PtrTy Ptr;
Expand Down Expand Up @@ -201,8 +202,7 @@ class APValue {

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;
Expand Down
26 changes: 18 additions & 8 deletions clang/lib/AST/APValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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} {}

Expand Down Expand Up @@ -82,13 +82,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());
}

namespace {
struct LVBase {
APValue::LValueBase Base;
Expand All @@ -113,14 +119,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 {
Expand Down Expand Up @@ -757,8 +765,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();
}
18 changes: 6 additions & 12 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1978,18 +1978,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) {
Expand Down Expand Up @@ -3108,7 +3101,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;
}
Expand Down
3 changes: 1 addition & 2 deletions clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
5 changes: 4 additions & 1 deletion clang/test/OpenMP/ordered_messages.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ void xxx(int argc) {
}

int foo();
#if __cplusplus >= 201103L
// expected-note@-2 {{declared here}}
#endif

template <class T>
T foo() {
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit e6393ee

Please sign in to comment.