[flang-commits] [flang] c87e94b - [flang] Get ProvenanceRange from CharBlock starting with expanded macro (#77791)

via flang-commits flang-commits at lists.llvm.org
Fri Jan 12 04:04:54 PST 2024


Author: jeanPerier
Date: 2024-01-12T13:04:50+01:00
New Revision: c87e94b0303cef11d24c5a3cf14bec570d850362

URL: https://github.com/llvm/llvm-project/commit/c87e94b0303cef11d24c5a3cf14bec570d850362
DIFF: https://github.com/llvm/llvm-project/commit/c87e94b0303cef11d24c5a3cf14bec570d850362.diff

LOG: [flang] Get ProvenanceRange from CharBlock starting with expanded macro (#77791)

When a CharBlock starts with an expanded macro but does not end in this
macro expansion, GetProvenanceRange fails to return a ProvenanceRange
which may cause error message to be emitted without location or lowering
to emit code without source location (which is problematic if this code
contains calls to procedures defined in the same file since LLVM will
later crash with the error:
"inlinable function call in a function with a DISubprogram location must
have a debug location"

Fix this situation by returning the ProvenanceRange starting at the
replaced macro reference.

Added: 
    flang/test/Semantics/assign15.f90

Modified: 
    flang/include/flang/Parser/provenance.h
    flang/lib/Parser/provenance.cpp
    flang/test/Lower/macro-debug-file-loc.f90

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Parser/provenance.h b/flang/include/flang/Parser/provenance.h
index 807718b1f7c35f..a5a5211144285d 100644
--- a/flang/include/flang/Parser/provenance.h
+++ b/flang/include/flang/Parser/provenance.h
@@ -161,6 +161,10 @@ class AllSources {
       ProvenanceRange def, ProvenanceRange use, const std::string &expansion);
   ProvenanceRange AddCompilerInsertion(std::string);
 
+  // If provenance is in an expanded macro, return the starting provenance of
+  // the replaced macro. Otherwise, return the input provenance.
+  Provenance GetReplacedProvenance(Provenance) const;
+
   bool IsValid(Provenance at) const { return range_.Contains(at); }
   bool IsValid(ProvenanceRange range) const {
     return range.size() > 0 && range_.Contains(range);
@@ -225,6 +229,8 @@ class AllSources {
 // single instances of CookedSource.
 class CookedSource {
 public:
+  explicit CookedSource(AllSources &allSources) : allSources_{allSources} {};
+
   int number() const { return number_; }
   void set_number(int n) { number_ = n; }
 
@@ -256,6 +262,7 @@ class CookedSource {
   llvm::raw_ostream &Dump(llvm::raw_ostream &) const;
 
 private:
+  AllSources &allSources_;
   int number_{0}; // for sorting purposes
   CharBuffer buffer_; // before Marshal()
   std::string data_; // all of it, prescanned and preprocessed

diff  --git a/flang/lib/Parser/provenance.cpp b/flang/lib/Parser/provenance.cpp
index b29bc4d1e6a6c1..3f185ffeb1b112 100644
--- a/flang/lib/Parser/provenance.cpp
+++ b/flang/lib/Parser/provenance.cpp
@@ -452,6 +452,14 @@ const AllSources::Origin &AllSources::MapToOrigin(Provenance at) const {
   return origin_[low];
 }
 
+Provenance AllSources::GetReplacedProvenance(Provenance provenance) const {
+  const Origin &origin{MapToOrigin(provenance)};
+  if (std::holds_alternative<Macro>(origin.u)) {
+    return origin.replaces.start();
+  }
+  return provenance;
+}
+
 std::optional<ProvenanceRange> CookedSource::GetProvenanceRange(
     CharBlock cookedRange) const {
   if (!AsCharBlock().Contains(cookedRange)) {
@@ -465,7 +473,16 @@ std::optional<ProvenanceRange> CookedSource::GetProvenanceRange(
   if (first.start() <= last.start()) {
     return {ProvenanceRange{first.start(), last.start() - first.start() + 1}};
   } else {
-    return std::nullopt;
+    // cookedRange may start (resp. end) in a macro expansion while it does not
+    // end (resp. start) in this macro expansion. Attempt to build a range
+    // over the replaced source.
+    Provenance firstStart{allSources_.GetReplacedProvenance(first.start())};
+    Provenance lastStart{allSources_.GetReplacedProvenance(last.start())};
+    if (firstStart <= lastStart) {
+      return {ProvenanceRange{firstStart, lastStart - firstStart + 1}};
+    } else {
+      return std::nullopt;
+    }
   }
 }
 
@@ -578,7 +595,7 @@ AllCookedSources::AllCookedSources(AllSources &s) : allSources_{s} {}
 AllCookedSources::~AllCookedSources() {}
 
 CookedSource &AllCookedSources::NewCookedSource() {
-  return cooked_.emplace_back();
+  return cooked_.emplace_back(allSources_);
 }
 
 const CookedSource *AllCookedSources::Find(CharBlock x) const {

diff  --git a/flang/test/Lower/macro-debug-file-loc.f90 b/flang/test/Lower/macro-debug-file-loc.f90
index a47c9aae178530..5e5665442d49a2 100644
--- a/flang/test/Lower/macro-debug-file-loc.f90
+++ b/flang/test/Lower/macro-debug-file-loc.f90
@@ -10,4 +10,18 @@ subroutine test()
   ! CHECK: fir.call @_QPfoo() fastmath<contract> : () -> () loc(#[[CALL_LOC:.*]])
   call CMD(foo)
 end subroutine
+
+#define IVAR i
+
+integer function ifoo()
+  ifoo = 0
+end function
+
+subroutine test2()
+  integer :: i
+  ! CHECK: fir.call @_QPifoo(){{.*}} loc(#[[IFOO_CALL_LOC:.*]])
+  IVAR = ifoo()
+end subroutine
+
 ! CHECK: #[[CALL_LOC]] = loc("{{.*}}macro-debug-file-loc.f90":11:3)
+! CHECK: #[[IFOO_CALL_LOC]] = loc("{{.*}}macro-debug-file-loc.f90":23:3)

diff  --git a/flang/test/Semantics/assign15.f90 b/flang/test/Semantics/assign15.f90
new file mode 100644
index 00000000000000..7df096c5b22e76
--- /dev/null
+++ b/flang/test/Semantics/assign15.f90
@@ -0,0 +1,12 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1
+! Test error location when assignment starts with macro expansion.
+
+#define X_VAR x
+program main
+  real(4) :: x
+  character(10) :: c
+  !ERROR: No intrinsic or user-defined ASSIGNMENT(=) matches operand types REAL(4) and CHARACTER(KIND=1)
+  X_VAR = c
+  !ERROR: No intrinsic or user-defined ASSIGNMENT(=) matches operand types CHARACTER(KIND=1) and REAL(4)
+  c = X_VAR
+end


        


More information about the flang-commits mailing list