Skip to content

Commit 9dcd96f

Browse files
committed
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 e6393ee with fixed handling for weak declarations. We now look for attributes on the most recent declaration when determining whether a declaration is weak. (Second recommit with further fixes for mishandling of weak declarations. Our behavior here is fundamentally unsound -- see PR47663 -- but this approach attempts to not make things worse.)
1 parent fa08afc commit 9dcd96f

File tree

9 files changed

+51
-31
lines changed

9 files changed

+51
-31
lines changed

clang/include/clang/AST/APValue.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ class APValue {
174174
return !(LHS == RHS);
175175
}
176176
friend llvm::hash_code hash_value(const LValueBase &Base);
177+
friend struct llvm::DenseMapInfo<LValueBase>;
177178

178179
private:
179180
PtrTy Ptr;
@@ -201,8 +202,7 @@ class APValue {
201202

202203
public:
203204
LValuePathEntry() : Value() {}
204-
LValuePathEntry(BaseOrMemberType BaseOrMember)
205-
: Value{reinterpret_cast<uintptr_t>(BaseOrMember.getOpaqueValue())} {}
205+
LValuePathEntry(BaseOrMemberType BaseOrMember);
206206
static LValuePathEntry ArrayIndex(uint64_t Index) {
207207
LValuePathEntry Result;
208208
Result.Value = Index;

clang/lib/AST/APValue.cpp

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ static_assert(
3838
"Type is insufficiently aligned");
3939

4040
APValue::LValueBase::LValueBase(const ValueDecl *P, unsigned I, unsigned V)
41-
: Ptr(P), Local{I, V} {}
41+
: Ptr(P ? cast<ValueDecl>(P->getCanonicalDecl()) : nullptr), Local{I, V} {}
4242
APValue::LValueBase::LValueBase(const Expr *P, unsigned I, unsigned V)
4343
: Ptr(P), Local{I, V} {}
4444

@@ -82,13 +82,19 @@ bool operator==(const APValue::LValueBase &LHS,
8282
const APValue::LValueBase &RHS) {
8383
if (LHS.Ptr != RHS.Ptr)
8484
return false;
85-
if (LHS.is<TypeInfoLValue>())
85+
if (LHS.is<TypeInfoLValue>() || LHS.is<DynamicAllocLValue>())
8686
return true;
8787
return LHS.Local.CallIndex == RHS.Local.CallIndex &&
8888
LHS.Local.Version == RHS.Local.Version;
8989
}
9090
}
9191

92+
APValue::LValuePathEntry::LValuePathEntry(BaseOrMemberType BaseOrMember) {
93+
if (const Decl *D = BaseOrMember.getPointer())
94+
BaseOrMember.setPointer(D->getCanonicalDecl());
95+
Value = reinterpret_cast<uintptr_t>(BaseOrMember.getOpaqueValue());
96+
}
97+
9298
namespace {
9399
struct LVBase {
94100
APValue::LValueBase Base;
@@ -113,14 +119,16 @@ APValue::LValueBase::operator bool () const {
113119

114120
clang::APValue::LValueBase
115121
llvm::DenseMapInfo<clang::APValue::LValueBase>::getEmptyKey() {
116-
return clang::APValue::LValueBase(
117-
DenseMapInfo<const ValueDecl*>::getEmptyKey());
122+
clang::APValue::LValueBase B;
123+
B.Ptr = DenseMapInfo<const ValueDecl*>::getEmptyKey();
124+
return B;
118125
}
119126

120127
clang::APValue::LValueBase
121128
llvm::DenseMapInfo<clang::APValue::LValueBase>::getTombstoneKey() {
122-
return clang::APValue::LValueBase(
123-
DenseMapInfo<const ValueDecl*>::getTombstoneKey());
129+
clang::APValue::LValueBase B;
130+
B.Ptr = DenseMapInfo<const ValueDecl*>::getTombstoneKey();
131+
return B;
124132
}
125133

126134
namespace clang {
@@ -773,8 +781,10 @@ void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
773781
assert(isAbsent() && "Bad state change");
774782
MemberPointerData *MPD = new ((void*)(char*)Data.buffer) MemberPointerData;
775783
Kind = MemberPointer;
776-
MPD->MemberAndIsDerivedMember.setPointer(Member);
784+
MPD->MemberAndIsDerivedMember.setPointer(
785+
Member ? cast<ValueDecl>(Member->getCanonicalDecl()) : nullptr);
777786
MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember);
778787
MPD->resizePath(Path.size());
779-
memcpy(MPD->getPath(), Path.data(), Path.size()*sizeof(const CXXRecordDecl*));
788+
for (unsigned I = 0; I != Path.size(); ++I)
789+
MPD->getPath()[I] = Path[I]->getCanonicalDecl();
780790
}

clang/lib/AST/Decl.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4686,11 +4686,9 @@ char *Buffer = new (getASTContext(), 1) char[Name.size() + 1];
46864686
void ValueDecl::anchor() {}
46874687

46884688
bool ValueDecl::isWeak() const {
4689-
for (const auto *I : attrs())
4690-
if (isa<WeakAttr>(I) || isa<WeakRefAttr>(I))
4691-
return true;
4692-
4693-
return isWeakImported();
4689+
auto *MostRecent = getMostRecentDecl();
4690+
return MostRecent->hasAttr<WeakAttr>() ||
4691+
MostRecent->hasAttr<WeakRefAttr>() || isWeakImported();
46944692
}
46954693

46964694
void ImplicitParamDecl::anchor() {}

clang/lib/AST/DeclBase.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -720,7 +720,7 @@ bool Decl::isWeakImported() const {
720720
if (!canBeWeakImported(IsDefinition))
721721
return false;
722722

723-
for (const auto *A : attrs()) {
723+
for (const auto *A : getMostRecentDecl()->attrs()) {
724724
if (isa<WeakImportAttr>(A))
725725
return true;
726726

clang/lib/AST/ExprConstant.cpp

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1978,18 +1978,11 @@ static bool HasSameBase(const LValue &A, const LValue &B) {
19781978
return false;
19791979

19801980
if (A.getLValueBase().getOpaqueValue() !=
1981-
B.getLValueBase().getOpaqueValue()) {
1982-
const Decl *ADecl = GetLValueBaseDecl(A);
1983-
if (!ADecl)
1984-
return false;
1985-
const Decl *BDecl = GetLValueBaseDecl(B);
1986-
if (!BDecl || ADecl->getCanonicalDecl() != BDecl->getCanonicalDecl())
1987-
return false;
1988-
}
1981+
B.getLValueBase().getOpaqueValue())
1982+
return false;
19891983

1990-
return IsGlobalLValue(A.getLValueBase()) ||
1991-
(A.getLValueCallIndex() == B.getLValueCallIndex() &&
1992-
A.getLValueVersion() == B.getLValueVersion());
1984+
return A.getLValueCallIndex() == B.getLValueCallIndex() &&
1985+
A.getLValueVersion() == B.getLValueVersion();
19931986
}
19941987

19951988
static void NoteLValueLocation(EvalInfo &Info, APValue::LValueBase Base) {
@@ -3158,7 +3151,8 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
31583151

31593152
// If we're currently evaluating the initializer of this declaration, use that
31603153
// in-flight value.
3161-
if (Info.EvaluatingDecl.dyn_cast<const ValueDecl*>() == VD) {
3154+
if (declaresSameEntity(Info.EvaluatingDecl.dyn_cast<const ValueDecl *>(),
3155+
VD)) {
31623156
Result = Info.EvaluatingDeclValue;
31633157
return true;
31643158
}

clang/lib/CodeGen/CGExprConstant.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1877,6 +1877,10 @@ ConstantLValue
18771877
ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) {
18781878
// Handle values.
18791879
if (const ValueDecl *D = base.dyn_cast<const ValueDecl*>()) {
1880+
// The constant always points to the canonical declaration. We want to look
1881+
// at properties of the most recent declaration at the point of emission.
1882+
D = cast<ValueDecl>(D->getMostRecentDecl());
1883+
18801884
if (D->hasAttr<WeakRefAttr>())
18811885
return CGM.GetWeakRefReference(D).getPointer();
18821886

clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,10 @@ constexpr double &ni3; // expected-error {{declaration of reference variable 'ni
2424

2525
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}}
2626
constexpr C nc2 = C(); // expected-error {{cannot have non-literal type 'const C'}}
27-
int &f(); // expected-note {{declared here}}
27+
int &f(); // expected-note 2{{declared here}}
2828
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}}
2929
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}}
3030
constexpr C nc5((C())); // expected-error {{cannot have non-literal type 'const C'}}
31-
int &f(); // expected-note {{here}}
3231
constexpr int &nc6(f()); // expected-error {{constexpr variable 'nc6' must be initialized by a constant expression}} expected-note {{non-constexpr function 'f'}}
3332

3433
struct pixel {

clang/test/CodeGenCXX/weak-external.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,15 @@ class _LIBCPP_EXCEPTION_ABI runtime_error
6464
void dummysymbol() {
6565
throw(std::runtime_error("string"));
6666
}
67+
68+
namespace not_weak_on_first {
69+
int func();
70+
// CHECK: {{.*}} extern_weak {{.*}} @_ZN17not_weak_on_first4funcEv(
71+
int func() __attribute__ ((weak));
72+
73+
typedef int (*FuncT)();
74+
75+
extern const FuncT table[] = {
76+
func,
77+
};
78+
}

clang/test/OpenMP/ordered_messages.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ void xxx(int argc) {
1616
}
1717

1818
int foo();
19+
#if __cplusplus >= 201103L
20+
// expected-note@-2 {{declared here}}
21+
#endif
1922

2023
template <class T>
2124
T foo() {
@@ -176,7 +179,7 @@ T foo() {
176179

177180
int foo() {
178181
#if __cplusplus >= 201103L
179-
// expected-note@-2 2 {{declared here}}
182+
// expected-note@-2 {{declared here}}
180183
#endif
181184
int k;
182185
#pragma omp for ordered

0 commit comments

Comments
 (0)