[flang][preprocessor] Finesse disabling of function-like macros (#71589)
During function-like macro expansion in a standard C/C++ preprocessor, the macro being expanded is disabled from recursive macro expansion. The implementation in this compiler's preprocessor, however, was too broad; the macro expansion needs to be disabled for the "rescanning" phase only, not for actual argument expansion. (Also corrects an obsolete comment elsewhere that was noticed during reduction of an original test case.)
This commit is contained in:
parent
9c1c56a803
commit
f2bf44b6ec
@ -397,9 +397,9 @@ std::optional<TokenSequence> Preprocessor::MacroReplacement(
|
|||||||
(n + 1 == argStart.size() ? k : argStart[n + 1] - 1) - at};
|
(n + 1 == argStart.size() ? k : argStart[n + 1] - 1) - at};
|
||||||
args.emplace_back(TokenSequence(input, at, count));
|
args.emplace_back(TokenSequence(input, at, count));
|
||||||
}
|
}
|
||||||
|
TokenSequence applied{def->Apply(args, prescanner)};
|
||||||
def->set_isDisabled(true);
|
def->set_isDisabled(true);
|
||||||
TokenSequence replaced{
|
TokenSequence replaced{ReplaceMacros(std::move(applied), prescanner)};
|
||||||
ReplaceMacros(def->Apply(args, prescanner), prescanner)};
|
|
||||||
def->set_isDisabled(false);
|
def->set_isDisabled(false);
|
||||||
if (!replaced.empty()) {
|
if (!replaced.empty()) {
|
||||||
ProvenanceRange from{def->replacement().GetProvenanceRange()};
|
ProvenanceRange from{def->replacement().GetProvenanceRange()};
|
||||||
|
@ -1285,11 +1285,15 @@ static void CheckAssociated(evaluate::ActualArguments &arguments,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (const auto &targetArg{arguments[1]}) {
|
if (const auto &targetArg{arguments[1]}) {
|
||||||
// The standard requires that the POINTER= argument be a valid LHS for
|
// The standard requires that the TARGET= argument, when present,
|
||||||
// a pointer assignment when the TARGET= argument is present. This,
|
// be a valid RHS for a pointer assignment that has the POINTER=
|
||||||
// perhaps unintentionally, excludes function results, including NULL(),
|
// argument as its LHS. Some popular compilers misinterpret this
|
||||||
// from being used there, as well as INTENT(IN) dummy pointers.
|
// requirement more strongly than necessary, and actually validate
|
||||||
// Allow this usage as a benign extension with a portability warning.
|
// the POINTER= argument as if it were serving as the LHS of a pointer
|
||||||
|
// assignment. This, perhaps unintentionally, excludes function
|
||||||
|
// results, including NULL(), from being used there, as well as
|
||||||
|
// INTENT(IN) dummy pointers. Detect these conditions and emit
|
||||||
|
// portability warnings.
|
||||||
if (!evaluate::ExtractDataRef(*pointerExpr) &&
|
if (!evaluate::ExtractDataRef(*pointerExpr) &&
|
||||||
!evaluate::IsProcedurePointer(*pointerExpr)) {
|
!evaluate::IsProcedurePointer(*pointerExpr)) {
|
||||||
context.messages().Say(pointerArg->sourceLocation(),
|
context.messages().Say(pointerArg->sourceLocation(),
|
||||||
|
14
flang/test/Preprocessing/disable-expansion.F90
Normal file
14
flang/test/Preprocessing/disable-expansion.F90
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
! RUN: %flang -E %s | FileCheck %s
|
||||||
|
#define KWM a
|
||||||
|
#define FLM(x) b FLM2(x) KWM c
|
||||||
|
#define FLM2(x) d FLM(x) e
|
||||||
|
! CHECK: a
|
||||||
|
KWM
|
||||||
|
! CHECK: b d FLM(y) e a c
|
||||||
|
FLM(y)
|
||||||
|
! CHECK: b d FLM(a) e a c
|
||||||
|
FLM(KWM)
|
||||||
|
! CHECK: b d FLM(b d FLM(y) e a c) e a c
|
||||||
|
FLM(FLM(y))
|
||||||
|
! CHECK: b d FLM(b d FLM(a) e a c) e a c
|
||||||
|
FLM(FLM(KWM))
|
Loading…
x
Reference in New Issue
Block a user