Index: clang/lib/AST/Interp/ByteCodeExprGen.h =================================================================== --- clang/lib/AST/Interp/ByteCodeExprGen.h +++ clang/lib/AST/Interp/ByteCodeExprGen.h @@ -287,6 +287,12 @@ /// Expression being initialized. llvm::Optional InitFn = {}; + + /// Returns whether we should create a global variable for the + /// given VarDecl. + bool isGlobalDecl(const VarDecl *VD) const { + return !VD->hasLocalStorage() || VD->isConstexpr(); + } }; extern template class ByteCodeExprGen; Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp =================================================================== --- clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -847,6 +847,10 @@ PrimType Ty, bool IsConst, bool IsExtended) { + // Make sure we don't accidentally register the same decl twice. + if (const Decl *VD = Src.dyn_cast(); VD && isa(VD)) + assert(!P.getGlobal(cast(VD))); + const Descriptor::MetadataSize MDSize{sizeof(InlineDescriptor)}; Descriptor *D = P.createDescriptor(Src, Ty, MDSize, IsConst, Src.is()); @@ -860,6 +864,10 @@ template llvm::Optional ByteCodeExprGen::allocateLocal(DeclTy &&Src, bool IsExtended) { + // Make sure we don't accidentally register the same decl twice. + if (const Decl *VD = Src.dyn_cast(); VD && isa(VD)) + assert(!P.getGlobal(cast(VD))); + const Descriptor::MetadataSize MDSize{sizeof(InlineDescriptor)}; QualType Ty; @@ -1162,35 +1170,44 @@ template bool ByteCodeExprGen::visitDecl(const VarDecl *VD) { const Expr *Init = VD->getInit(); + Optional GlobalIndex; - if (Optional I = P.createGlobal(VD, Init)) { - if (Optional T = classify(VD->getType())) { - { - // Primitive declarations - compute the value and set it. - DeclScope LocalScope(this, VD); - if (!visit(Init)) - return false; - } + if (isGlobalDecl(VD)) { + GlobalIndex = P.createGlobal(VD, Init); + + if (!GlobalIndex) + return this->bail(VD); + } + + if (Optional T = classify(VD->getType())) { + { + // Primitive declarations - compute the value and set it. + DeclScope LocalScope(this, VD); + if (!visit(Init)) + return false; + } + if (GlobalIndex) { // If the declaration is global, save the value for later use. if (!this->emitDup(*T, VD)) return false; - if (!this->emitInitGlobal(*T, *I, VD)) + if (!this->emitInitGlobal(*T, *GlobalIndex, VD)) return false; - return this->emitRet(*T, VD); - } else { - { - // Composite declarations - allocate storage and initialize it. - DeclScope LocalScope(this, VD); - if (!visitGlobalInitializer(Init, *I)) - return false; - } - - // Return a pointer to the global. - if (!this->emitGetPtrGlobal(*I, VD)) + } + return this->emitRet(*T, VD); + } else { + assert(GlobalIndex); + { + // Composite declarations - allocate storage and initialize it. + DeclScope LocalScope(this, VD); + if (!visitGlobalInitializer(Init, *GlobalIndex)) return false; - return this->emitRetValue(VD); } + + // Return a pointer to the global. + if (!this->emitGetPtrGlobal(*GlobalIndex, VD)) + return false; + return this->emitRetValue(VD); } return this->bail(VD); Index: clang/lib/AST/Interp/ByteCodeStmtGen.cpp =================================================================== --- clang/lib/AST/Interp/ByteCodeStmtGen.cpp +++ clang/lib/AST/Interp/ByteCodeStmtGen.cpp @@ -388,8 +388,8 @@ template bool ByteCodeStmtGen::visitVarDecl(const VarDecl *VD) { - if (!VD->hasLocalStorage()) { - // No code generation required. + if (this->isGlobalDecl(VD)) { + // Has already been registred as a global variable. return true; }