andreybokhanko created this revision. andreybokhanko added reviewers: rjmccall, rsmith. andreybokhanko added a subscriber: cfe-commits.
This patch fixes compiler crash described in the following thread: http://lists.cs.uiuc.edu/pipermail/cfe-dev/2015-July/thread.html#43852. It also fixes incorrect behavior described in PR17829. In essence, I inserted a check in GetAddrOfFunction that verifies that no two different declarations correspond to the same mangled name. Given that clang defers everything, this is the best suitable place I managed to find for the check. Also, the check makes sense only if one of declarations is a C++ method, as there are some kinds of non-C++ declarations that can correctly have the same mangled name (inline assembly inserts is an example). Yours, Andrey Bokhanko ============ Software Engineer Intel Compiler Team Intel http://reviews.llvm.org/D11297 Files: lib/CodeGen/CGExpr.cpp lib/CodeGen/CodeGenModule.cpp test/CodeGenCXX/duplicate-mangled-name.cpp Index: lib/CodeGen/CodeGenModule.cpp =================================================================== --- lib/CodeGen/CodeGenModule.cpp +++ lib/CodeGen/CodeGenModule.cpp @@ -1666,6 +1666,21 @@ Ty = getTypes().ConvertType(cast<ValueDecl>(GD.getDecl())->getType()); StringRef MangledName = getMangledName(GD); + + // Check that there are no declarations with the same mangled name. This check + // is valid only if one of declarations is a C++ method. + GlobalDecl OldGD; + if (lookupRepresentativeDecl(MangledName, OldGD) && + (isa<CXXMethodDecl>(GD.getDecl()) || + isa<CXXMethodDecl>(OldGD.getDecl())) && + GD.getCanonicalDecl().getDecl() != OldGD.getCanonicalDecl().getDecl()) { + getDiags().Report(GD.getDecl()->getLocation(), + diag::err_duplicate_mangled_name); + getDiags().Report(OldGD.getDecl()->getLocation(), + diag::note_previous_definition); + return llvm::UndefValue::get(VoidPtrTy); + } + return GetOrCreateLLVMFunction(MangledName, Ty, GD, ForVTable, DontDefer); } @@ -2401,6 +2416,9 @@ llvm::Constant *C = GetAddrOfFunction(GD, Ty, /*ForVTable=*/false, /*DontDefer*/ true); + if (isa<llvm::UndefValue>(C)) + return; + // Strip off a bitcast if we got one back. if (auto *CE = dyn_cast<llvm::ConstantExpr>(C)) { assert(CE->getOpcode() == llvm::Instruction::BitCast); Index: lib/CodeGen/CGExpr.cpp =================================================================== --- lib/CodeGen/CGExpr.cpp +++ lib/CodeGen/CGExpr.cpp @@ -3181,6 +3181,10 @@ } llvm::Value *Callee = EmitScalarExpr(E->getCallee()); + + if (isa<llvm::UndefValue>(Callee)) + return RValue::get(Callee); + return EmitCall(E->getCallee()->getType(), Callee, E, ReturnValue, TargetDecl); } Index: test/CodeGenCXX/duplicate-mangled-name.cpp =================================================================== --- test/CodeGenCXX/duplicate-mangled-name.cpp +++ test/CodeGenCXX/duplicate-mangled-name.cpp @@ -1,10 +1,31 @@ -// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm-only %s -verify +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm-only -DTEST1 %s -verify +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm-only -DTEST2 %s -verify // rdar://15522601 +#ifdef TEST1 class MyClass { static void meth(); }; void MyClass::meth() { } // expected-note {{previous}} extern "C" { void _ZN7MyClass4methEv() { } // expected-error {{definition with same mangled name as another definition}} } + +#elif TEST2 + +extern "C" void _ZN1TD1Ev(); // expected-error {{definition with same mangled name as another definition}} +struct T { + ~T() {} // expected-note {{previous}} +}; + +int main() { + _ZN1TD1Ev(); + T t; +} + +#else + +#error Unknown test mode + +#endif +
Index: lib/CodeGen/CodeGenModule.cpp =================================================================== --- lib/CodeGen/CodeGenModule.cpp +++ lib/CodeGen/CodeGenModule.cpp @@ -1666,6 +1666,21 @@ Ty = getTypes().ConvertType(cast<ValueDecl>(GD.getDecl())->getType()); StringRef MangledName = getMangledName(GD); + + // Check that there are no declarations with the same mangled name. This check + // is valid only if one of declarations is a C++ method. + GlobalDecl OldGD; + if (lookupRepresentativeDecl(MangledName, OldGD) && + (isa<CXXMethodDecl>(GD.getDecl()) || + isa<CXXMethodDecl>(OldGD.getDecl())) && + GD.getCanonicalDecl().getDecl() != OldGD.getCanonicalDecl().getDecl()) { + getDiags().Report(GD.getDecl()->getLocation(), + diag::err_duplicate_mangled_name); + getDiags().Report(OldGD.getDecl()->getLocation(), + diag::note_previous_definition); + return llvm::UndefValue::get(VoidPtrTy); + } + return GetOrCreateLLVMFunction(MangledName, Ty, GD, ForVTable, DontDefer); } @@ -2401,6 +2416,9 @@ llvm::Constant *C = GetAddrOfFunction(GD, Ty, /*ForVTable=*/false, /*DontDefer*/ true); + if (isa<llvm::UndefValue>(C)) + return; + // Strip off a bitcast if we got one back. if (auto *CE = dyn_cast<llvm::ConstantExpr>(C)) { assert(CE->getOpcode() == llvm::Instruction::BitCast); Index: lib/CodeGen/CGExpr.cpp =================================================================== --- lib/CodeGen/CGExpr.cpp +++ lib/CodeGen/CGExpr.cpp @@ -3181,6 +3181,10 @@ } llvm::Value *Callee = EmitScalarExpr(E->getCallee()); + + if (isa<llvm::UndefValue>(Callee)) + return RValue::get(Callee); + return EmitCall(E->getCallee()->getType(), Callee, E, ReturnValue, TargetDecl); } Index: test/CodeGenCXX/duplicate-mangled-name.cpp =================================================================== --- test/CodeGenCXX/duplicate-mangled-name.cpp +++ test/CodeGenCXX/duplicate-mangled-name.cpp @@ -1,10 +1,31 @@ -// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm-only %s -verify +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm-only -DTEST1 %s -verify +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm-only -DTEST2 %s -verify // rdar://15522601 +#ifdef TEST1 class MyClass { static void meth(); }; void MyClass::meth() { } // expected-note {{previous}} extern "C" { void _ZN7MyClass4methEv() { } // expected-error {{definition with same mangled name as another definition}} } + +#elif TEST2 + +extern "C" void _ZN1TD1Ev(); // expected-error {{definition with same mangled name as another definition}} +struct T { + ~T() {} // expected-note {{previous}} +}; + +int main() { + _ZN1TD1Ev(); + T t; +} + +#else + +#error Unknown test mode + +#endif +
_______________________________________________ cfe-commits mailing list cfe-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits