diff --git a/clang/lib/AST/Interp/ByteCodeEmitter.cpp b/clang/lib/AST/Interp/ByteCodeEmitter.cpp --- a/clang/lib/AST/Interp/ByteCodeEmitter.cpp +++ b/clang/lib/AST/Interp/ByteCodeEmitter.cpp @@ -22,51 +22,50 @@ Expected ByteCodeEmitter::compileFunc(const FunctionDecl *FuncDecl) { - // Create a handle over the emitted code. - Function *Func = P.getFunction(FuncDecl); - if (!Func) { - // Set up argument indices. - unsigned ParamOffset = 0; - SmallVector ParamTypes; - llvm::DenseMap ParamDescriptors; - - // If the return is not a primitive, a pointer to the storage where the - // value is initialized in is passed as the first argument. See 'RVO' - // elsewhere in the code. - QualType Ty = FuncDecl->getReturnType(); - bool HasRVO = false; - if (!Ty->isVoidType() && !Ctx.classify(Ty)) { - HasRVO = true; - ParamTypes.push_back(PT_Ptr); - ParamOffset += align(primSize(PT_Ptr)); - } + // Set up argument indices. + unsigned ParamOffset = 0; + SmallVector ParamTypes; + llvm::DenseMap ParamDescriptors; + + // If the return is not a primitive, a pointer to the storage where the + // value is initialized in is passed as the first argument. See 'RVO' + // elsewhere in the code. + QualType Ty = FuncDecl->getReturnType(); + bool HasRVO = false; + if (!Ty->isVoidType() && !Ctx.classify(Ty)) { + HasRVO = true; + ParamTypes.push_back(PT_Ptr); + ParamOffset += align(primSize(PT_Ptr)); + } - // If the function decl is a member decl, the next parameter is - // the 'this' pointer. This parameter is pop()ed from the - // InterpStack when calling the function. - bool HasThisPointer = false; - if (const auto *MD = dyn_cast(FuncDecl); - MD && MD->isInstance()) { - HasThisPointer = true; - ParamTypes.push_back(PT_Ptr); - ParamOffset += align(primSize(PT_Ptr)); - } + // If the function decl is a member decl, the next parameter is + // the 'this' pointer. This parameter is pop()ed from the + // InterpStack when calling the function. + bool HasThisPointer = false; + if (const auto *MD = dyn_cast(FuncDecl); + MD && MD->isInstance()) { + HasThisPointer = true; + ParamTypes.push_back(PT_Ptr); + ParamOffset += align(primSize(PT_Ptr)); + } - // Assign descriptors to all parameters. - // Composite objects are lowered to pointers. - for (const ParmVarDecl *PD : FuncDecl->parameters()) { - PrimType Ty = Ctx.classify(PD->getType()).value_or(PT_Ptr); - Descriptor *Desc = P.createDescriptor(PD, Ty); - ParamDescriptors.insert({ParamOffset, {Ty, Desc}}); - Params.insert({PD, ParamOffset}); - ParamOffset += align(primSize(Ty)); - ParamTypes.push_back(Ty); - } + // Assign descriptors to all parameters. + // Composite objects are lowered to pointers. + for (const ParmVarDecl *PD : FuncDecl->parameters()) { + PrimType Ty = Ctx.classify(PD->getType()).value_or(PT_Ptr); + Descriptor *Desc = P.createDescriptor(PD, Ty); + ParamDescriptors.insert({ParamOffset, {Ty, Desc}}); + Params.insert({PD, ParamOffset}); + ParamOffset += align(primSize(Ty)); + ParamTypes.push_back(Ty); + } + // Create a handle over the emitted code. + Function *Func = P.getFunction(FuncDecl); + if (!Func) Func = P.createFunction(FuncDecl, ParamOffset, std::move(ParamTypes), std::move(ParamDescriptors), HasThisPointer, HasRVO); - } assert(Func); // For not-yet-defined functions, we only create a Function instance and diff --git a/clang/test/AST/Interp/functions.cpp b/clang/test/AST/Interp/functions.cpp --- a/clang/test/AST/Interp/functions.cpp +++ b/clang/test/AST/Interp/functions.cpp @@ -180,3 +180,8 @@ return 1; } }; + +constexpr int nyd(int m); +constexpr int doit() { return nyd(10); } +constexpr int nyd(int m) { return m; } +static_assert(doit() == 10);