diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1985,7 +1985,9 @@ FuncAttrs.addAttribute(llvm::Attribute::NoReturn); NBA = Fn->getAttr(); } - if (!AttrOnCallSite && TargetDecl->hasAttr()) + // Only place nomerge attribute on call sites, never functions. This + // allows it to work on indirect virtual function calls. + if (AttrOnCallSite && TargetDecl->hasAttr()) FuncAttrs.addAttribute(llvm::Attribute::NoMerge); } @@ -5018,13 +5020,11 @@ Attrs.addAttribute(getLLVMContext(), llvm::AttributeList::FunctionIndex, llvm::Attribute::StrictFP); - // Add nomerge attribute to the call-site if the callee function doesn't have - // the attribute. - if (const FunctionDecl *FD = dyn_cast_or_null(TargetDecl)) - if (!FD->hasAttr() && InNoMergeAttributedStmt) - Attrs = Attrs.addAttribute(getLLVMContext(), - llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoMerge); + // Add call-site nomerge attribute if exists. + if (InNoMergeAttributedStmt) + Attrs = + Attrs.addAttribute(getLLVMContext(), llvm::AttributeList::FunctionIndex, + llvm::Attribute::NoMerge); // Apply some call-site-specific attributes. // TODO: work this into building the attribute set. diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1772,9 +1772,6 @@ B.addAttribute(llvm::Attribute::MinSize); } - if (D->hasAttr()) - B.addAttribute(llvm::Attribute::NoMerge); - F->addAttributes(llvm::AttributeList::FunctionIndex, B); unsigned alignment = D->getMaxAlignment() / Context.getCharWidth(); diff --git a/clang/test/CodeGen/attr-nomerge.cpp b/clang/test/CodeGen/attr-nomerge.cpp --- a/clang/test/CodeGen/attr-nomerge.cpp +++ b/clang/test/CodeGen/attr-nomerge.cpp @@ -3,7 +3,7 @@ class A { public: [[clang::nomerge]] A(); - [[clang::nomerge]] ~A(); + [[clang::nomerge]] virtual ~A(); [[clang::nomerge]] void f(); [[clang::nomerge]] virtual void g(); [[clang::nomerge]] static void f1(); @@ -14,14 +14,14 @@ void g() override; }; -[[clang::nomerge]] bool bar(); +bool bar(); [[clang::nomerge]] void f(bool, bool); void foo(int i, A *ap, B *bp) { [[clang::nomerge]] bar(); [[clang::nomerge]] (i = 4, bar()); [[clang::nomerge]] (void)(bar()); - [[clang::nomerge]] f(bar(), bar()); + f(bar(), bar()); [[clang::nomerge]] [] { bar(); bar(); }(); // nomerge only applies to the anonymous function call [[clang::nomerge]] for (bar(); bar(); bar()) {} [[clang::nomerge]] { asm("nop"); } @@ -37,6 +37,9 @@ B b; b.g(); + + A *newA = new B(); + delete newA; } int g(int i); @@ -57,37 +60,34 @@ g(1); } +// CHECK: call zeroext i1 @_Z3barv() #[[ATTR0:[0-9]+]] +// CHECK: call zeroext i1 @_Z3barv() #[[ATTR0]] +// CHECK: call zeroext i1 @_Z3barv() #[[ATTR0]] // CHECK: call zeroext i1 @_Z3barv(){{$}} // CHECK: call zeroext i1 @_Z3barv(){{$}} -// CHECK: call zeroext i1 @_Z3barv(){{$}} -// CHECK: call zeroext i1 @_Z3barv(){{$}} -// CHECK: call zeroext i1 @_Z3barv(){{$}} -// CHECK: call void @_Z1fbb({{.*}}){{$}} -// CHECK: call void @"_ZZ3fooiP1AP1BENK3$_0clEv"{{.*}} #[[ATTR0:[0-9]+]] -// CHECK: call zeroext i1 @_Z3barv(){{$}} -// CHECK: call zeroext i1 @_Z3barv(){{$}} -// CHECK: call zeroext i1 @_Z3barv(){{$}} +// CHECK: call void @_Z1fbb({{.*}}) #[[ATTR0]] +// CHECK: call void @"_ZZ3fooiP1AP1BENK3$_0clEv"{{.*}} #[[ATTR0]] +// CHECK: call zeroext i1 @_Z3barv() #[[ATTR0]] +// CHECK-LABEL: for.cond: +// CHECK: call zeroext i1 @_Z3barv() #[[ATTR0]] +// CHECK-LABEL: for.inc: +// CHECK: call zeroext i1 @_Z3barv() #[[ATTR0]] // CHECK: call void asm sideeffect "nop"{{.*}} #[[ATTR1:[0-9]+]] // CHECK: call zeroext i1 @_Z3barv(){{$}} // CHECK: %[[AG:.*]] = load void (%class.A*)*, void (%class.A*)** -// CHECK-NEXT: call void %[[AG]](%class.A* nonnull dereferenceable +// CHECK-NEXT: call void %[[AG]](%class.A* {{.*}}) #[[ATTR0]] // CHECK: %[[BG:.*]] = load void (%class.B*)*, void (%class.B*)** // CHECK-NEXT: call void %[[BG]](%class.B* nonnull dereferenceable - - -// CHECK-DAG: declare zeroext i1 @_Z3barv() #[[ATTR2:[0-9]+]] -// CHECK-DAG: declare void @_Z1fbb(i1 zeroext, i1 zeroext) #[[ATTR2]] -// CHECK-DAG: declare void @_ZN1AC1Ev{{.*}} #[[ATTR2]] -// CHECK-DAG: declare void @_ZN1A1fEv{{.*}} #[[ATTR2]] -// CHECK-DAG: declare void @_ZN1A1gEv{{.*}} #[[ATTR2]] -// CHECK-DAG: declare void @_ZN1A2f1Ev{{.*}} #[[ATTR2]] -// CHECK-DAG: declare void @_ZN1AC2Ev{{.*}} #[[ATTR2]] -// CHECK-DAG: declare void @_ZN1AD1Ev{{.*}} #[[ATTR3:[0-9]+]] -// CHECK-DAG: declare void @_ZN1AD2Ev{{.*}} #[[ATTR3]] -// CHECK-DAG: define{{.*}} i32 @_Z1gi(i32 %i) #[[ATTR4:[0-9]+]] { +// CHECK: call void @_ZN1AC1Ev({{.*}}) #[[ATTR0]] +// CHECK: call void @_ZN1A1fEv({{.*}}) #[[ATTR0]] +// CHECK: call void @_ZN1A1gEv({{.*}}) #[[ATTR0]] +// CHECK: call void @_ZN1A2f1Ev() #[[ATTR0]] +// CHECK: call void @_ZN1BC1Ev({{.*}}){{$}} +// CHECK: call void @_ZN1B1gEv({{.*}}){{$}} +// CHECK: call void @_ZN1BC1Ev({{.*}}){{$}} +// CHECK: %[[AG:.*]] = load void (%class.A*)*, void (%class.A*)** +// CHECK-NEXT: call void %[[AG]](%class.A* {{.*}}) #[[ATTR1]] +// CHECK: call void @_ZN1AD1Ev(%class.A* {{.*}}) #[[ATTR1]] // CHECK-DAG: attributes #[[ATTR0]] = {{{.*}}nomerge{{.*}}} // CHECK-DAG: attributes #[[ATTR1]] = {{{.*}}nomerge{{.*}}} -// CHECK-DAG: attributes #[[ATTR2]] = {{{.*}}nomerge{{.*}}} -// CHECK-DAG: attributes #[[ATTR3]] = {{{.*}}nomerge{{.*}}} -// CHECK-DAG: attributes #[[ATTR4]] = {{{.*}}nomerge{{.*}}}