forked from OSchip/llvm-project
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 ofe6393ee813
, most recently reverted in9a33f027ac
due to a bug caused by ObjCInterfaceDecls not propagating availability attributes along their redeclaration chains; that bug was fixed ine2d4174e9c
.
This commit is contained in:
parent
e2d4174e9c
commit
913f600566
|
@ -177,6 +177,7 @@ public:
|
||||||
return !(LHS == RHS);
|
return !(LHS == RHS);
|
||||||
}
|
}
|
||||||
friend llvm::hash_code hash_value(const LValueBase &Base);
|
friend llvm::hash_code hash_value(const LValueBase &Base);
|
||||||
|
friend struct llvm::DenseMapInfo<LValueBase>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PtrTy Ptr;
|
PtrTy Ptr;
|
||||||
|
@ -204,8 +205,7 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LValuePathEntry() : Value() {}
|
LValuePathEntry() : Value() {}
|
||||||
LValuePathEntry(BaseOrMemberType BaseOrMember)
|
LValuePathEntry(BaseOrMemberType BaseOrMember);
|
||||||
: Value{reinterpret_cast<uintptr_t>(BaseOrMember.getOpaqueValue())} {}
|
|
||||||
static LValuePathEntry ArrayIndex(uint64_t Index) {
|
static LValuePathEntry ArrayIndex(uint64_t Index) {
|
||||||
LValuePathEntry Result;
|
LValuePathEntry Result;
|
||||||
Result.Value = Index;
|
Result.Value = Index;
|
||||||
|
|
|
@ -38,7 +38,7 @@ static_assert(
|
||||||
"Type is insufficiently aligned");
|
"Type is insufficiently aligned");
|
||||||
|
|
||||||
APValue::LValueBase::LValueBase(const ValueDecl *P, unsigned I, unsigned V)
|
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)
|
APValue::LValueBase::LValueBase(const Expr *P, unsigned I, unsigned V)
|
||||||
: Ptr(P), Local{I, V} {}
|
: Ptr(P), Local{I, V} {}
|
||||||
|
|
||||||
|
@ -90,13 +90,19 @@ bool operator==(const APValue::LValueBase &LHS,
|
||||||
const APValue::LValueBase &RHS) {
|
const APValue::LValueBase &RHS) {
|
||||||
if (LHS.Ptr != RHS.Ptr)
|
if (LHS.Ptr != RHS.Ptr)
|
||||||
return false;
|
return false;
|
||||||
if (LHS.is<TypeInfoLValue>())
|
if (LHS.is<TypeInfoLValue>() || LHS.is<DynamicAllocLValue>())
|
||||||
return true;
|
return true;
|
||||||
return LHS.Local.CallIndex == RHS.Local.CallIndex &&
|
return LHS.Local.CallIndex == RHS.Local.CallIndex &&
|
||||||
LHS.Local.Version == RHS.Local.Version;
|
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 {
|
void APValue::LValuePathEntry::profile(llvm::FoldingSetNodeID &ID) const {
|
||||||
ID.AddInteger(Value);
|
ID.AddInteger(Value);
|
||||||
}
|
}
|
||||||
|
@ -125,14 +131,16 @@ APValue::LValueBase::operator bool () const {
|
||||||
|
|
||||||
clang::APValue::LValueBase
|
clang::APValue::LValueBase
|
||||||
llvm::DenseMapInfo<clang::APValue::LValueBase>::getEmptyKey() {
|
llvm::DenseMapInfo<clang::APValue::LValueBase>::getEmptyKey() {
|
||||||
return clang::APValue::LValueBase(
|
clang::APValue::LValueBase B;
|
||||||
DenseMapInfo<const ValueDecl*>::getEmptyKey());
|
B.Ptr = DenseMapInfo<const ValueDecl*>::getEmptyKey();
|
||||||
|
return B;
|
||||||
}
|
}
|
||||||
|
|
||||||
clang::APValue::LValueBase
|
clang::APValue::LValueBase
|
||||||
llvm::DenseMapInfo<clang::APValue::LValueBase>::getTombstoneKey() {
|
llvm::DenseMapInfo<clang::APValue::LValueBase>::getTombstoneKey() {
|
||||||
return clang::APValue::LValueBase(
|
clang::APValue::LValueBase B;
|
||||||
DenseMapInfo<const ValueDecl*>::getTombstoneKey());
|
B.Ptr = DenseMapInfo<const ValueDecl*>::getTombstoneKey();
|
||||||
|
return B;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
|
@ -926,8 +934,10 @@ void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
|
||||||
assert(isAbsent() && "Bad state change");
|
assert(isAbsent() && "Bad state change");
|
||||||
MemberPointerData *MPD = new ((void*)(char*)Data.buffer) MemberPointerData;
|
MemberPointerData *MPD = new ((void*)(char*)Data.buffer) MemberPointerData;
|
||||||
Kind = MemberPointer;
|
Kind = MemberPointer;
|
||||||
MPD->MemberAndIsDerivedMember.setPointer(Member);
|
MPD->MemberAndIsDerivedMember.setPointer(
|
||||||
|
Member ? cast<ValueDecl>(Member->getCanonicalDecl()) : nullptr);
|
||||||
MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember);
|
MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember);
|
||||||
MPD->resizePath(Path.size());
|
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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4686,11 +4686,9 @@ char *Buffer = new (getASTContext(), 1) char[Name.size() + 1];
|
||||||
void ValueDecl::anchor() {}
|
void ValueDecl::anchor() {}
|
||||||
|
|
||||||
bool ValueDecl::isWeak() const {
|
bool ValueDecl::isWeak() const {
|
||||||
for (const auto *I : attrs())
|
auto *MostRecent = getMostRecentDecl();
|
||||||
if (isa<WeakAttr>(I) || isa<WeakRefAttr>(I))
|
return MostRecent->hasAttr<WeakAttr>() ||
|
||||||
return true;
|
MostRecent->hasAttr<WeakRefAttr>() || isWeakImported();
|
||||||
|
|
||||||
return isWeakImported();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImplicitParamDecl::anchor() {}
|
void ImplicitParamDecl::anchor() {}
|
||||||
|
|
|
@ -720,7 +720,7 @@ bool Decl::isWeakImported() const {
|
||||||
if (!canBeWeakImported(IsDefinition))
|
if (!canBeWeakImported(IsDefinition))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (const auto *A : attrs()) {
|
for (const auto *A : getMostRecentDecl()->attrs()) {
|
||||||
if (isa<WeakImportAttr>(A))
|
if (isa<WeakImportAttr>(A))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
|
@ -1982,18 +1982,11 @@ static bool HasSameBase(const LValue &A, const LValue &B) {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (A.getLValueBase().getOpaqueValue() !=
|
if (A.getLValueBase().getOpaqueValue() !=
|
||||||
B.getLValueBase().getOpaqueValue()) {
|
B.getLValueBase().getOpaqueValue())
|
||||||
const Decl *ADecl = GetLValueBaseDecl(A);
|
return false;
|
||||||
if (!ADecl)
|
|
||||||
return false;
|
|
||||||
const Decl *BDecl = GetLValueBaseDecl(B);
|
|
||||||
if (!BDecl || ADecl->getCanonicalDecl() != BDecl->getCanonicalDecl())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return IsGlobalLValue(A.getLValueBase()) ||
|
return A.getLValueCallIndex() == B.getLValueCallIndex() &&
|
||||||
(A.getLValueCallIndex() == B.getLValueCallIndex() &&
|
A.getLValueVersion() == B.getLValueVersion();
|
||||||
A.getLValueVersion() == B.getLValueVersion());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void NoteLValueLocation(EvalInfo &Info, APValue::LValueBase Base) {
|
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
|
// If we're currently evaluating the initializer of this declaration, use that
|
||||||
// in-flight value.
|
// in-flight value.
|
||||||
if (Info.EvaluatingDecl.dyn_cast<const ValueDecl*>() == VD) {
|
if (declaresSameEntity(Info.EvaluatingDecl.dyn_cast<const ValueDecl *>(),
|
||||||
|
VD)) {
|
||||||
Result = Info.EvaluatingDeclValue;
|
Result = Info.EvaluatingDeclValue;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1877,6 +1877,10 @@ ConstantLValue
|
||||||
ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) {
|
ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) {
|
||||||
// Handle values.
|
// Handle values.
|
||||||
if (const ValueDecl *D = base.dyn_cast<const ValueDecl*>()) {
|
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>())
|
if (D->hasAttr<WeakRefAttr>())
|
||||||
return CGM.GetWeakRefReference(D).getPointer();
|
return CGM.GetWeakRefReference(D).getPointer();
|
||||||
|
|
||||||
|
|
|
@ -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 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'}}
|
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 &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 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'}}
|
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'}}
|
constexpr int &nc6(f()); // expected-error {{constexpr variable 'nc6' must be initialized by a constant expression}} expected-note {{non-constexpr function 'f'}}
|
||||||
|
|
||||||
struct pixel {
|
struct pixel {
|
||||||
|
|
|
@ -64,3 +64,15 @@ public:
|
||||||
void dummysymbol() {
|
void dummysymbol() {
|
||||||
throw(std::runtime_error("string"));
|
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,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -16,6 +16,9 @@ void xxx(int argc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int foo();
|
int foo();
|
||||||
|
#if __cplusplus >= 201103L
|
||||||
|
// expected-note@-2 {{declared here}}
|
||||||
|
#endif
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
T foo() {
|
T foo() {
|
||||||
|
@ -176,7 +179,7 @@ T foo() {
|
||||||
|
|
||||||
int foo() {
|
int foo() {
|
||||||
#if __cplusplus >= 201103L
|
#if __cplusplus >= 201103L
|
||||||
// expected-note@-2 2 {{declared here}}
|
// expected-note@-2 {{declared here}}
|
||||||
#endif
|
#endif
|
||||||
int k;
|
int k;
|
||||||
#pragma omp for ordered
|
#pragma omp for ordered
|
||||||
|
|
Loading…
Reference in New Issue