Index: lib/AST/VTableBuilder.cpp =================================================================== --- lib/AST/VTableBuilder.cpp +++ lib/AST/VTableBuilder.cpp @@ -138,6 +138,7 @@ /// the subobject with the given base offset. OverriderInfo getOverrider(const CXXMethodDecl *MD, CharUnits BaseOffset) const { + MD = MD->getCanonicalDecl(); assert(OverridersMap.count(std::make_pair(MD, BaseOffset)) && "Did not find overrider!"); @@ -1697,7 +1698,7 @@ assert(MethodVTableIndices.empty()); for (MethodInfoMapTy::const_iterator I = MethodInfoMap.begin(), E = MethodInfoMap.end(); I != E; ++I) { - const CXXMethodDecl *MD = I->first; + const CXXMethodDecl *MD = I->first->getCanonicalDecl(); const MethodInfo &MI = I->second; if (const CXXDestructorDecl *DD = dyn_cast(MD)) { MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] @@ -2196,6 +2197,7 @@ // We only want virtual member functions. if (!MD->isVirtual()) continue; + MD = MD->getCanonicalDecl(); std::string MethodName = PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual, @@ -2557,7 +2559,7 @@ assert(MethodVFTableLocations.empty()); for (MethodInfoMapTy::const_iterator I = MethodInfoMap.begin(), E = MethodInfoMap.end(); I != E; ++I) { - const CXXMethodDecl *MD = I->first; + const CXXMethodDecl *MD = I->first->getCanonicalDecl(); const MethodInfo &MI = I->second; // Skip the methods that the MostDerivedClass didn't override // and the entries shadowed by return adjusting thunks. Index: test/Modules/Inputs/merge-vtable-codegen/a.h =================================================================== --- /dev/null +++ test/Modules/Inputs/merge-vtable-codegen/a.h @@ -0,0 +1,8 @@ +#ifndef A_H +#define A_H + +struct A { + virtual void x(); +}; + +#endif Index: test/Modules/Inputs/merge-vtable-codegen/a.modulemap =================================================================== --- /dev/null +++ test/Modules/Inputs/merge-vtable-codegen/a.modulemap @@ -0,0 +1,3 @@ +module "a" { + textual header "a.h" +} Index: test/Modules/Inputs/merge-vtable-codegen/b.h =================================================================== --- /dev/null +++ test/Modules/Inputs/merge-vtable-codegen/b.h @@ -0,0 +1,10 @@ +#ifndef B_H +#define B_H + +#include "a.h" + +void b(A* p) { + p->x(); +} + +#endif Index: test/Modules/Inputs/merge-vtable-codegen/b.modulemap =================================================================== --- /dev/null +++ test/Modules/Inputs/merge-vtable-codegen/b.modulemap @@ -0,0 +1,7 @@ +module "b" { + header "b.h" + use "a" +} + +extern module "a" "a.modulemap" + Index: test/Modules/Inputs/merge-vtable-codegen/c.h =================================================================== --- /dev/null +++ test/Modules/Inputs/merge-vtable-codegen/c.h @@ -0,0 +1,6 @@ +#ifndef C_H +#define C_H + +#include "a.h" + +#endif Index: test/Modules/Inputs/merge-vtable-codegen/c.modulemap =================================================================== --- /dev/null +++ test/Modules/Inputs/merge-vtable-codegen/c.modulemap @@ -0,0 +1,6 @@ +module "c" { + header "c.h" + use "a" +} + +extern module "a" "a.modulemap" \ No newline at end of file Index: test/Modules/Inputs/merge-vtable-codegen/merge-vtable-codegen.modulemap =================================================================== --- /dev/null +++ test/Modules/Inputs/merge-vtable-codegen/merge-vtable-codegen.modulemap @@ -0,0 +1,8 @@ +module "merge-vtable-codegen" { + export * + use "b" + use "c" +} + +extern module "b" "b.modulemap" +extern module "c" "c.modulemap" \ No newline at end of file Index: test/Modules/merge-vtable-codegen.cpp =================================================================== --- /dev/null +++ test/Modules/merge-vtable-codegen.cpp @@ -0,0 +1,24 @@ +// RUN: rm -rf %t + +// First, build two modules that both re-export the same header. +// RUN: %clang_cc1 -x c++ -std=c++11 -fmodules -fmodule-name=b -o %t/b.pcm -fmodule-maps \ +// RUN: -emit-module %S/Inputs/merge-vtable-codegen/b.modulemap \ +// RUN: -I %S/Inputs/merge-vtable-codegen +// RUN: %clang_cc1 -x c++ -std=c++11 -fmodules -fmodule-name=c -o %t/c.pcm -fmodule-maps \ +// RUN: -emit-module %S/Inputs/merge-vtable-codegen/c.modulemap \ +// RUN: -I %S/Inputs/merge-vtable-codegen + +// Use the two modules in a single compile. +// RUN: %clang_cc1 -x c++ -std=c++11 -fmodules -fmodule-file=%t/b.pcm -fmodule-file=%t/c.pcm \ +// RUN: -emit-llvm -o %t/test.o %s -fmodule-name=merge-vtable-codegen \ +// RUN: -fmodule-map-file=%S/Inputs/merge-vtable-codegen/merge-vtable-codegen.modulemap + +// Note that order is important: +// Module 'c' just reexports A, while module 'b' defines a method that uses a +// virtual method of A. +#include "Inputs/merge-vtable-codegen/c.h" +#include "Inputs/merge-vtable-codegen/b.h" + +void t() { + b(nullptr); +}