diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 1af7cd9ee0d..8acdf384004 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -1553,22 +1553,22 @@ void AsmParser::HandleMacroExit() { ActiveMacros.pop_back(); } -static void MarkUsed(const MCExpr *Value) { +static bool IsUsedIn(const MCSymbol *Sym, const MCExpr *Value) { switch (Value->getKind()) { - case MCExpr::Binary: - MarkUsed(static_cast(Value)->getLHS()); - MarkUsed(static_cast(Value)->getRHS()); - break; - case MCExpr::Target: - case MCExpr::Constant: - break; - case MCExpr::SymbolRef: { - static_cast(Value)->getSymbol().setUsed(true); + case MCExpr::Binary: { + const MCBinaryExpr *BE = static_cast(Value); + return IsUsedIn(Sym, BE->getLHS()) || IsUsedIn(Sym, BE->getRHS()); break; } + case MCExpr::Target: + case MCExpr::Constant: + return false; + case MCExpr::SymbolRef: { + const MCSymbol &S = static_cast(Value)->getSymbol(); + return &S.AliasedSymbol() == Sym; + } case MCExpr::Unary: - MarkUsed(static_cast(Value)->getSubExpr()); - break; + return IsUsedIn(Sym, static_cast(Value)->getSubExpr()); } } @@ -1580,7 +1580,9 @@ bool AsmParser::ParseAssignment(StringRef Name, bool allow_redef) { if (ParseExpression(Value)) return true; - MarkUsed(Value); + // Note: we don't count b as used in "a = b". This is to allow + // a = b + // b = c if (Lexer.isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in assignment"); @@ -1602,7 +1604,9 @@ bool AsmParser::ParseAssignment(StringRef Name, bool allow_redef) { // // FIXME: Diagnostics. Note the location of the definition as a label. // FIXME: Diagnose assignment to protected identifier (e.g., register name). - if (Sym->isUndefined() && !Sym->isUsed() && !Sym->isVariable()) + if (IsUsedIn(Sym, Value)) + return Error(EqualLoc, "Recursive use of '" + Name + "'"); + else if (Sym->isUndefined() && !Sym->isUsed() && !Sym->isVariable()) ; // Allow redefinitions of undefined symbols only used in directives. else if (!Sym->isUndefined() && (!Sym->isVariable() || !allow_redef)) return Error(EqualLoc, "redefinition of '" + Name + "'"); diff --git a/test/MC/AsmParser/pr11865.s b/test/MC/AsmParser/pr11865.s new file mode 100644 index 00000000000..1c03e117d98 --- /dev/null +++ b/test/MC/AsmParser/pr11865.s @@ -0,0 +1,6 @@ +// RUN: llvm-mc -triple i386-unknown-unknown %s + +i: + .long g +g = h +h = i diff --git a/test/MC/AsmParser/variables-invalid.s b/test/MC/AsmParser/variables-invalid.s index 9656889c5b1..c0f6c398767 100644 --- a/test/MC/AsmParser/variables-invalid.s +++ b/test/MC/AsmParser/variables-invalid.s @@ -2,7 +2,7 @@ // RUN: FileCheck --input-file %t %s .data -// CHECK: invalid assignment to 't0_v0' +// CHECK: Recursive use of 't0_v0' t0_v0 = t0_v0 + 1 t1_v1 = 1 @@ -15,3 +15,9 @@ t2_s0: t3_s0 = t2_s0 + 1 // CHECK: invalid reassignment of non-absolute variable 't3_s0' t3_s0 = 1 + + +// CHECK: Recursive use of 't4_s2' + t4_s0 = t4_s1 + t4_s1 = t4_s2 + t4_s2 = t4_s0