[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.
This commit is contained in:
parent
a762cc2155
commit
c87e94b030
@ -161,6 +161,10 @@ public:
|
|||||||
ProvenanceRange def, ProvenanceRange use, const std::string &expansion);
|
ProvenanceRange def, ProvenanceRange use, const std::string &expansion);
|
||||||
ProvenanceRange AddCompilerInsertion(std::string);
|
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(Provenance at) const { return range_.Contains(at); }
|
||||||
bool IsValid(ProvenanceRange range) const {
|
bool IsValid(ProvenanceRange range) const {
|
||||||
return range.size() > 0 && range_.Contains(range);
|
return range.size() > 0 && range_.Contains(range);
|
||||||
@ -225,6 +229,8 @@ private:
|
|||||||
// single instances of CookedSource.
|
// single instances of CookedSource.
|
||||||
class CookedSource {
|
class CookedSource {
|
||||||
public:
|
public:
|
||||||
|
explicit CookedSource(AllSources &allSources) : allSources_{allSources} {};
|
||||||
|
|
||||||
int number() const { return number_; }
|
int number() const { return number_; }
|
||||||
void set_number(int n) { number_ = n; }
|
void set_number(int n) { number_ = n; }
|
||||||
|
|
||||||
@ -256,6 +262,7 @@ public:
|
|||||||
llvm::raw_ostream &Dump(llvm::raw_ostream &) const;
|
llvm::raw_ostream &Dump(llvm::raw_ostream &) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
AllSources &allSources_;
|
||||||
int number_{0}; // for sorting purposes
|
int number_{0}; // for sorting purposes
|
||||||
CharBuffer buffer_; // before Marshal()
|
CharBuffer buffer_; // before Marshal()
|
||||||
std::string data_; // all of it, prescanned and preprocessed
|
std::string data_; // all of it, prescanned and preprocessed
|
||||||
|
@ -452,6 +452,14 @@ const AllSources::Origin &AllSources::MapToOrigin(Provenance at) const {
|
|||||||
return origin_[low];
|
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(
|
std::optional<ProvenanceRange> CookedSource::GetProvenanceRange(
|
||||||
CharBlock cookedRange) const {
|
CharBlock cookedRange) const {
|
||||||
if (!AsCharBlock().Contains(cookedRange)) {
|
if (!AsCharBlock().Contains(cookedRange)) {
|
||||||
@ -465,7 +473,16 @@ std::optional<ProvenanceRange> CookedSource::GetProvenanceRange(
|
|||||||
if (first.start() <= last.start()) {
|
if (first.start() <= last.start()) {
|
||||||
return {ProvenanceRange{first.start(), last.start() - first.start() + 1}};
|
return {ProvenanceRange{first.start(), last.start() - first.start() + 1}};
|
||||||
} else {
|
} 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() {}
|
AllCookedSources::~AllCookedSources() {}
|
||||||
|
|
||||||
CookedSource &AllCookedSources::NewCookedSource() {
|
CookedSource &AllCookedSources::NewCookedSource() {
|
||||||
return cooked_.emplace_back();
|
return cooked_.emplace_back(allSources_);
|
||||||
}
|
}
|
||||||
|
|
||||||
const CookedSource *AllCookedSources::Find(CharBlock x) const {
|
const CookedSource *AllCookedSources::Find(CharBlock x) const {
|
||||||
|
@ -10,4 +10,18 @@ subroutine test()
|
|||||||
! CHECK: fir.call @_QPfoo() fastmath<contract> : () -> () loc(#[[CALL_LOC:.*]])
|
! CHECK: fir.call @_QPfoo() fastmath<contract> : () -> () loc(#[[CALL_LOC:.*]])
|
||||||
call CMD(foo)
|
call CMD(foo)
|
||||||
end subroutine
|
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: #[[CALL_LOC]] = loc("{{.*}}macro-debug-file-loc.f90":11:3)
|
||||||
|
! CHECK: #[[IFOO_CALL_LOC]] = loc("{{.*}}macro-debug-file-loc.f90":23:3)
|
||||||
|
12
flang/test/Semantics/assign15.f90
Normal file
12
flang/test/Semantics/assign15.f90
Normal file
@ -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
|
Loading…
x
Reference in New Issue
Block a user