Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp =================================================================== --- clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -845,15 +845,38 @@ template bool ByteCodeExprGen::VisitDeclRefExpr(const DeclRefExpr *E) { const auto *Decl = E->getDecl(); + bool IsReference = Decl->getType()->isReferenceType(); + bool FoundDecl = false; if (auto It = Locals.find(Decl); It != Locals.end()) { const unsigned Offset = It->second.Offset; - return this->emitGetPtrLocal(Offset, E); + if (!this->emitGetPtrLocal(Offset, E)) + return false; + + FoundDecl = true; } else if (auto GlobalIndex = P.getGlobal(Decl)) { - return this->emitGetPtrGlobal(*GlobalIndex, E); + if (!this->emitGetPtrGlobal(*GlobalIndex, E)) + return false; + + FoundDecl = true; } else if (const auto *PVD = dyn_cast(Decl)) { - if (auto It = this->Params.find(PVD); It != this->Params.end()) - return this->emitGetPtrParam(It->second, E); + if (auto It = this->Params.find(PVD); It != this->Params.end()) { + if (!this->emitGetPtrParam(It->second, E)) + return false; + + FoundDecl = true; + } + } + + // References are implemented using pointers, so when we get here, + // we have a pointer to a pointer, which we need to de-reference once. + if (FoundDecl) { + if (IsReference) { + if (!this->emitLoadPop(PT_Ptr, E)) + return false; + } + + return true; } return false; Index: clang/test/AST/Interp/references.cpp =================================================================== --- /dev/null +++ clang/test/AST/Interp/references.cpp @@ -0,0 +1,62 @@ +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify %s +// RUN: %clang_cc1 -verify=ref %s + + +// expected-no-diagnostics +// ref-no-diagnostics + +constexpr int a = 10; +constexpr const int &b = a; +static_assert(a == b, ""); + +constexpr int assignToReference() { + int a = 20; + int &b =a; + + b = 100; + return a; +} +static_assert(assignToReference() == 100, ""); + + +constexpr void setValue(int &dest, int val) { + dest = val; +} + +constexpr int checkSetValue() { + int l = 100; + setValue(l, 200); + return l; +} +static_assert(checkSetValue() == 200, ""); + +constexpr int readLocalRef() { + int a = 20; + int &b = a; + return b; +} +static_assert(readLocalRef() == 20, ""); + +constexpr int incRef() { + int a = 0; + int &b = a; + + b = b + 1; + + return a; +} +static_assert(incRef() == 1, ""); + + +template +constexpr void Plus3(int &A) { + A = V + 3; +} +constexpr int foo = 4; + +constexpr int callTemplate() { + int a = 3; + Plus3(a); + return a; +} +static_assert(callTemplate() == 7, "");