nickdesaulniers updated this revision to Diff 488368.
nickdesaulniers marked an inline comment as done.
nickdesaulniers added a comment.

- replace inlined-from w/ inlined.from


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D141451/new/

https://reviews.llvm.org/D141451

Files:
  clang/include/clang/Basic/DiagnosticFrontendKinds.td
  clang/lib/CodeGen/CodeGenAction.cpp
  clang/test/Frontend/backend-attribute-error-warning-optimize.c
  clang/test/Frontend/backend-attribute-error-warning.c
  clang/test/Frontend/backend-attribute-error-warning.cpp
  llvm/include/llvm/IR/DiagnosticInfo.h
  llvm/lib/IR/DiagnosticInfo.cpp
  llvm/lib/Transforms/Utils/InlineFunction.cpp
  llvm/test/Transforms/Inline/dontcall-attributes.ll

Index: llvm/test/Transforms/Inline/dontcall-attributes.ll
===================================================================
--- /dev/null
+++ llvm/test/Transforms/Inline/dontcall-attributes.ll
@@ -0,0 +1,84 @@
+; RUN: opt -S -o - -passes=inline %s \
+; RUN:  | FileCheck %s --check-prefixes=CHECK-BOTH,CHECK
+; RUN: opt -S -o - -passes=always-inline %s \
+; RUN:  | FileCheck %s --check-prefixes=CHECK-BOTH,CHECK-ALWAYS
+
+declare void @foo() "dontcall-warn"="oh no"
+declare void @fof() "dontcall-error"="oh no"
+
+define void @bar(i32 %x) {
+  %cmp = icmp eq i32 %x, 10
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  call void @foo()
+  br label %if.end
+
+if.end:
+  ret void
+}
+
+define void @quux() {
+  call void @bar(i32 9)
+  ret void
+}
+
+; Test that @baz's call to @foo has metadata with inlining info.
+define void @baz() {
+; CHECK-LABEL: @baz(
+; CHECK-NEXT:    call void @foo(), !inlined.from !0
+;
+  call void @bar(i32 10)
+  ret void
+}
+
+; Test that @zing's call to @foo has unique metadata from @baz's call to @foo.
+define void @zing() {
+; CHECK-LABEL: @zing(
+; CHECK-NEXT:    call void @foo(), !inlined.from !1
+;
+  call void @baz()
+  ret void
+}
+
+; Same test but @fof has fn attr "dontcall-error"="..." rather than
+; "dontcall-warn"="...".
+define void @a() {
+  call void @fof()
+  ret void
+}
+define void @b() {
+; CHECK-LABEL: @b(
+; CHECK-NEXT: call void @fof(), !inlined.from !3
+  call void @a()
+  ret void
+}
+
+; Add some tests for alwaysinline.
+define void @always_callee() alwaysinline {
+  call void @fof()
+  ret void
+}
+define void @always_caller() alwaysinline {
+; CHECK-BOTH-LABEL: @always_caller(
+; CHECK-NEXT: call void @fof(), !inlined.from !4
+; CHECK-ALWAYS-NEXT: call void @fof(), !inlined.from !0
+  call void @always_callee()
+  ret void
+}
+define void @always_caller2() alwaysinline {
+; CHECK-BOTH-LABEL: @always_caller2(
+; CHECK-NEXT: call void @fof(), !inlined.from !5
+; CHECK-ALWAYS-NEXT: call void @fof(), !inlined.from !1
+  call void @always_caller()
+  ret void
+}
+
+; CHECK: !0 = !{!"bar"}
+; CHECK-NEXT: !1 = !{!2}
+; CHECK-NEXT: !2 = !{!"bar", !"baz"}
+; CHECK-NEXT: !3 = !{!"a"}
+; CHECK-NEXT: !4 = !{!"always_callee"}
+; CHECK-ALWAYS: !0 = !{!"always_callee"}
+; CHECK-ALWAYS-NEXT: !1 = !{!2}
+; CHECK-ALWAYS-NEXT: !2 = !{!"always_callee", !"always_caller"}
Index: llvm/lib/Transforms/Utils/InlineFunction.cpp
===================================================================
--- llvm/lib/Transforms/Utils/InlineFunction.cpp
+++ llvm/lib/Transforms/Utils/InlineFunction.cpp
@@ -2463,6 +2463,19 @@
         // inlining, commonly when the callee is an intrinsic.
         if (MarkNoUnwind && !CI->doesNotThrow())
           CI->setDoesNotThrow();
+
+        const Function *Callee = CI->getCalledFunction();
+        if (Callee && (Callee->hasFnAttribute("dontcall-error") ||
+                       Callee->hasFnAttribute("dontcall-warn"))) {
+          Metadata *MD = MDString::get(CI->getContext(), CalledFunc->getName());
+          if (MDNode *N = CI->getMetadata("inlined.from")) {
+            TempMDTuple Temp = cast<MDTuple>(N)->clone();
+            Temp->push_back(MD);
+            MD = MDNode::replaceWithUniqued(std::move(Temp));
+          }
+          MDTuple *MDT = MDNode::get(CI->getContext(), {MD});
+          CI->setMetadata("inlined.from", MDT);
+        }
       }
     }
   }
Index: llvm/lib/IR/DiagnosticInfo.cpp
===================================================================
--- llvm/lib/IR/DiagnosticInfo.cpp
+++ llvm/lib/IR/DiagnosticInfo.cpp
@@ -12,9 +12,11 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/ADT/iterator_range.h"
+#include "llvm/Demangle/Demangle.h"
 #include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/DebugInfoMetadata.h"
@@ -430,8 +432,9 @@
       if (MDNode *MD = CI.getMetadata("srcloc"))
         LocCookie =
             mdconst::extract<ConstantInt>(MD->getOperand(0))->getZExtValue();
-      DiagnosticInfoDontCall D(F->getName(), A.getValueAsString(), Sev,
-                               LocCookie);
+      DiagnosticInfoDontCall D(CI.getParent()->getParent()->getName(),
+                               F->getName(), A.getValueAsString(), Sev,
+                               LocCookie, CI.getMetadata("inlined.from"));
       F->getContext().diagnose(D);
     }
   }
@@ -446,3 +449,20 @@
   if (!getNote().empty())
     DP << ": " << getNote();
 }
+
+void DiagnosticInfoDontCall::getInliningDecisions(
+    SmallVectorImpl<std::string> &InliningDecisions) const {
+  if (!MDN)
+    return;
+
+  const MDOperand &MO = MDN->getOperand(0);
+  if (auto *MDT = dyn_cast<MDTuple>(MO)) {
+    for (unsigned i = MDT->getNumOperands(); i; --i) {
+      if (auto *S = dyn_cast<MDString>(MDT->getOperand(i - 1))) {
+        InliningDecisions.push_back(S->getString().str());
+      }
+    }
+  } else if (auto *S = dyn_cast<MDString>(MO)) {
+    InliningDecisions.push_back(S->getString().str());
+  }
+}
Index: llvm/include/llvm/IR/DiagnosticInfo.h
===================================================================
--- llvm/include/llvm/IR/DiagnosticInfo.h
+++ llvm/include/llvm/IR/DiagnosticInfo.h
@@ -1099,15 +1099,19 @@
 void diagnoseDontCall(const CallInst &CI);
 
 class DiagnosticInfoDontCall : public DiagnosticInfo {
+  StringRef CallerName;
   StringRef CalleeName;
   StringRef Note;
   unsigned LocCookie;
+  MDNode *MDN;
 
 public:
-  DiagnosticInfoDontCall(StringRef CalleeName, StringRef Note,
-                         DiagnosticSeverity DS, unsigned LocCookie)
-      : DiagnosticInfo(DK_DontCall, DS), CalleeName(CalleeName), Note(Note),
-        LocCookie(LocCookie) {}
+  DiagnosticInfoDontCall(StringRef CallerName, StringRef CalleeName,
+                         StringRef Note, DiagnosticSeverity DS,
+                         unsigned LocCookie, MDNode *MDN)
+      : DiagnosticInfo(DK_DontCall, DS), CallerName(CallerName),
+        CalleeName(CalleeName), Note(Note), LocCookie(LocCookie), MDN(MDN) {}
+  StringRef getCaller() const { return CallerName; }
   StringRef getFunctionName() const { return CalleeName; }
   StringRef getNote() const { return Note; }
   unsigned getLocCookie() const { return LocCookie; }
@@ -1115,6 +1119,8 @@
   static bool classof(const DiagnosticInfo *DI) {
     return DI->getKind() == DK_DontCall;
   }
+  void
+  getInliningDecisions(SmallVectorImpl<std::string> &InliningDecisions) const;
 };
 
 } // end namespace llvm
Index: clang/test/Frontend/backend-attribute-error-warning.cpp
===================================================================
--- clang/test/Frontend/backend-attribute-error-warning.cpp
+++ clang/test/Frontend/backend-attribute-error-warning.cpp
@@ -24,13 +24,19 @@
 
 void baz(void) {
   foo(); // expected-error {{call to 'foo()' declared with 'error' attribute: oh no foo}}
+         // expected-note@* {{In function 'baz()'}}
   if (x())
     bar(); // expected-error {{call to 'bar()' declared with 'error' attribute: oh no bar}}
+           // expected-note@* {{In function 'baz()'}}
 
   quux();                     // enabled-warning {{call to 'quux()' declared with 'warning' attribute: oh no quux}}
+                              // enabled-note@* {{In function 'baz()'}}
   __compiletime_assert_455(); // expected-error {{call to '__compiletime_assert_455()' declared with 'error' attribute: demangle me}}
+                              // expected-note@* {{In function 'baz()'}}
   duplicate_errors();         // expected-error {{call to 'duplicate_errors()' declared with 'error' attribute: two}}
+                              // expected-note@* {{In function 'baz()'}}
   duplicate_warnings();       // enabled-warning {{call to 'duplicate_warnings()' declared with 'warning' attribute: two}}
+                              // enabled-note@* {{In function 'baz()'}}
 }
 
 #ifdef __cplusplus
@@ -46,15 +52,21 @@
 
 void baz_cpp(void) {
   foo(); // expected-error {{call to 'foo()' declared with 'error' attribute: oh no foo}}
+         // expected-note@* {{In function 'baz_cpp()'}}
   if (x())
     bar(); // expected-error {{call to 'bar()' declared with 'error' attribute: oh no bar}}
+           // expected-note@* {{In function 'baz_cpp()'}}
   quux();  // enabled-warning {{call to 'quux()' declared with 'warning' attribute: oh no quux}}
+           // enabled-note@* {{In function 'baz_cpp()'}}
 
   // Test that we demangle correctly in the diagnostic for C++.
   __compiletime_assert_455(); // expected-error {{call to '__compiletime_assert_455()' declared with 'error' attribute: demangle me}}
+                              // expected-note@* {{In function 'baz_cpp()'}}
   nocall<int>(42);            // expected-error {{call to 'int nocall<int>(int)' declared with 'error' attribute: demangle me, too}}
+                              // expected-note@* {{In function 'baz_cpp()'}}
 
   Widget W;
   int w = W; // enabled-warning {{call to 'Widget::operator int()' declared with 'warning' attribute: don't call me!}}
+             // enabled-note@* {{In function 'baz_cpp()'}}
 }
 #endif
Index: clang/test/Frontend/backend-attribute-error-warning.c
===================================================================
--- clang/test/Frontend/backend-attribute-error-warning.c
+++ clang/test/Frontend/backend-attribute-error-warning.c
@@ -23,11 +23,17 @@
 
 void baz(void) {
   foo(); // expected-error {{call to 'foo' declared with 'error' attribute: oh no foo}}
+         // expected-note@* {{In function 'baz'}}
   if (x())
     bar(); // expected-error {{call to 'bar' declared with 'error' attribute: oh no bar}}
+           // expected-note@* {{In function 'baz'}}
 
   quux();                     // enabled-warning {{call to 'quux' declared with 'warning' attribute: oh no quux}}
+                              // enabled-note@* {{In function 'baz'}}
   __compiletime_assert_455(); // expected-error {{call to '__compiletime_assert_455' declared with 'error' attribute: demangle me}}
+                              // expected-note@* {{In function 'baz'}}
   duplicate_errors();         // expected-error {{call to 'duplicate_errors' declared with 'error' attribute: two}}
+                              // expected-note@* {{In function 'baz'}}
   duplicate_warnings();       // enabled-warning {{call to 'duplicate_warnings' declared with 'warning' attribute: two}}
+                              // enabled-note@* {{In function 'baz'}}
 }
Index: clang/test/Frontend/backend-attribute-error-warning-optimize.c
===================================================================
--- clang/test/Frontend/backend-attribute-error-warning-optimize.c
+++ clang/test/Frontend/backend-attribute-error-warning-optimize.c
@@ -9,6 +9,7 @@
 }
 void baz(void) {
   foo(); // expected-error {{call to 'foo' declared with 'error' attribute: oh no foo}}
+         // expected-note@* {{In function 'baz'}}
   if (x())
     bar();
 }
@@ -20,3 +21,23 @@
   quux = foo;
   quux();
 }
+
+static inline void a(int x) {
+    if (x == 10)
+        foo(); // expected-error {{call to 'foo' declared with 'error' attribute: oh no foo}}
+               // expected-note@* {{In function 'd'}}
+               // expected-note@* {{which inlined function 'b'}}
+               // expected-note@* {{which inlined function 'a'}}
+}
+
+static inline void b() {
+    a(10);
+}
+
+void c() {
+    a(9);
+}
+
+void d() {
+  b();
+}
Index: clang/lib/CodeGen/CodeGenAction.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenAction.cpp
+++ clang/lib/CodeGen/CodeGenAction.cpp
@@ -49,6 +49,8 @@
 #include "llvm/Transforms/IPO/Internalize.h"
 
 #include <memory>
+#include <string>
+
 using namespace clang;
 using namespace llvm;
 
@@ -851,6 +853,13 @@
                               ? diag::err_fe_backend_error_attr
                               : diag::warn_fe_backend_warning_attr)
       << llvm::demangle(D.getFunctionName().str()) << D.getNote();
+
+  Diags.Report(diag::note_fe_backend_in) << llvm::demangle(D.getCaller().str());
+
+  SmallVector<std::string, 4> InliningDecisions;
+  D.getInliningDecisions(InliningDecisions);
+  for (const std::string &S : InliningDecisions)
+    Diags.Report(diag::note_fe_backend_inlined) << llvm::demangle(S);
 }
 
 void BackendConsumer::MisExpectDiagHandler(
Index: clang/include/clang/Basic/DiagnosticFrontendKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -90,6 +90,8 @@
 def warn_fe_backend_warning_attr :
   Warning<"call to '%0' declared with 'warning' attribute: %1">, BackendInfo,
   InGroup<BackendWarningAttributes>;
+def note_fe_backend_in : Note<"In function '%0'">;
+def note_fe_backend_inlined : Note<"\twhich inlined function '%0'">;
 
 def err_fe_invalid_code_complete_file : Error<
     "cannot locate code-completion file %0">, DefaultFatal;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to