summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/MC/MCParser/AsmParser.cpp71
-rw-r--r--test/MC/AsmParser/macro-qualifier-diagnostics.s64
-rw-r--r--test/MC/AsmParser/macro-qualifier.s16
3 files changed, 139 insertions, 12 deletions
diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp
index 1692b2f190..f73e56ade2 100644
--- a/lib/MC/MCParser/AsmParser.cpp
+++ b/lib/MC/MCParser/AsmParser.cpp
@@ -58,6 +58,9 @@ typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments;
struct MCAsmMacroParameter {
StringRef Name;
MCAsmMacroArgument Value;
+ bool Required;
+
+ MCAsmMacroParameter() : Required(false) { }
};
typedef std::vector<MCAsmMacroParameter> MCAsmMacroParameters;
@@ -1940,26 +1943,23 @@ bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA) {
bool AsmParser::parseMacroArguments(const MCAsmMacro *M,
MCAsmMacroArguments &A) {
const unsigned NParameters = M ? M->Parameters.size() : 0;
+ bool NamedParametersFound = false;
+ SmallVector<SMLoc, 4> FALocs;
A.resize(NParameters);
- for (unsigned PI = 0; PI < NParameters; ++PI)
- if (!M->Parameters[PI].Value.empty())
- A[PI] = M->Parameters[PI].Value;
-
- bool NamedParametersFound = false;
+ FALocs.resize(NParameters);
// Parse two kinds of macro invocations:
// - macros defined without any parameters accept an arbitrary number of them
// - macros defined with parameters accept at most that many of them
for (unsigned Parameter = 0; !NParameters || Parameter < NParameters;
++Parameter) {
+ SMLoc IDLoc = Lexer.getLoc();
MCAsmMacroParameter FA;
- SMLoc L;
if (Lexer.is(AsmToken::Identifier) && Lexer.peekTok().is(AsmToken::Equal)) {
- L = Lexer.getLoc();
if (parseIdentifier(FA.Name)) {
- Error(L, "invalid argument identifier for formal argument");
+ Error(IDLoc, "invalid argument identifier for formal argument");
eatToEndOfStatement();
return true;
}
@@ -1975,7 +1975,7 @@ bool AsmParser::parseMacroArguments(const MCAsmMacro *M,
}
if (NamedParametersFound && FA.Name.empty()) {
- Error(Lexer.getLoc(), "cannot mix positional and keyword arguments");
+ Error(IDLoc, "cannot mix positional and keyword arguments");
eatToEndOfStatement();
return true;
}
@@ -1989,8 +1989,9 @@ bool AsmParser::parseMacroArguments(const MCAsmMacro *M,
for (FAI = 0; FAI < NParameters; ++FAI)
if (M->Parameters[FAI].Name == FA.Name)
break;
+
if (FAI >= NParameters) {
- Error(L,
+ Error(IDLoc,
"parameter named '" + FA.Name + "' does not exist for macro '" +
M->Name + "'");
return true;
@@ -2002,13 +2003,33 @@ bool AsmParser::parseMacroArguments(const MCAsmMacro *M,
if (A.size() <= PI)
A.resize(PI + 1);
A[PI] = FA.Value;
+
+ if (FALocs.size() <= PI)
+ FALocs.resize(PI + 1);
+
+ FALocs[PI] = Lexer.getLoc();
}
// At the end of the statement, fill in remaining arguments that have
// default values. If there aren't any, then the next argument is
// required but missing
- if (Lexer.is(AsmToken::EndOfStatement))
- return false;
+ if (Lexer.is(AsmToken::EndOfStatement)) {
+ bool Failure = false;
+ for (unsigned FAI = 0; FAI < NParameters; ++FAI) {
+ if (A[FAI].empty()) {
+ if (M->Parameters[FAI].Required) {
+ Error(FALocs[FAI].isValid() ? FALocs[FAI] : Lexer.getLoc(),
+ "missing value for required parameter "
+ "'" + M->Parameters[FAI].Name + "' in macro '" + M->Name + "'");
+ Failure = true;
+ }
+
+ if (!M->Parameters[FAI].Value.empty())
+ A[FAI] = M->Parameters[FAI].Value;
+ }
+ }
+ return Failure;
+ }
if (Lexer.is(AsmToken::Comma))
Lex();
@@ -3210,10 +3231,36 @@ bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) {
if (parseIdentifier(Parameter.Name))
return TokError("expected identifier in '.macro' directive");
+ if (Lexer.is(AsmToken::Colon)) {
+ Lex(); // consume ':'
+
+ SMLoc QualLoc;
+ StringRef Qualifier;
+
+ QualLoc = Lexer.getLoc();
+ if (parseIdentifier(Qualifier))
+ return Error(QualLoc, "missing parameter qualifier for "
+ "'" + Parameter.Name + "' in macro '" + Name + "'");
+
+ if (Qualifier == "req")
+ Parameter.Required = true;
+ else
+ return Error(QualLoc, Qualifier + " is not a valid parameter qualifier "
+ "for '" + Parameter.Name + "' in macro '" + Name + "'");
+ }
+
if (getLexer().is(AsmToken::Equal)) {
Lex();
+
+ SMLoc ParamLoc;
+
+ ParamLoc = Lexer.getLoc();
if (parseMacroArgument(Parameter.Value))
return true;
+
+ if (Parameter.Required)
+ Warning(ParamLoc, "pointless default value for required parameter "
+ "'" + Parameter.Name + "' in macro '" + Name + "'");
}
Parameters.push_back(Parameter);
diff --git a/test/MC/AsmParser/macro-qualifier-diagnostics.s b/test/MC/AsmParser/macro-qualifier-diagnostics.s
new file mode 100644
index 0000000000..4ebad2b69e
--- /dev/null
+++ b/test/MC/AsmParser/macro-qualifier-diagnostics.s
@@ -0,0 +1,64 @@
+# RUN: not llvm-mc -triple i386 -o /dev/null %s 2>&1 | FileCheck %s
+
+ .macro missing_qualifier parameter:
+
+# CHECK: error: missing parameter qualifier for 'parameter' in macro 'missing_qualifier'
+# CHECK: .macro missing_qualifier parameter:
+# CHECK: ^
+
+ .macro non_identifier_qualifier parameter:0
+
+# CHECK: error: missing parameter qualifier for 'parameter' in macro 'non_identifier_qualifier'
+# CHECK: .macro non_identifier_qualifier parameter:0
+# CHECK: ^
+
+ .macro invalid_qualifier parameter:invalid_qualifier
+
+# CHECK: error: invalid_qualifier is not a valid parameter qualifier for 'parameter' in macro 'invalid_qualifier'
+# CHECK: .macro invalid_qualifier parameter:invalid_qualifier
+# CHECK: ^
+
+ .macro pointless_default parameter:req=default
+ .endm
+
+# CHECK: warning: pointless default value for required parameter 'parameter' in macro 'pointless_default'
+# CHECK: .macro pointless_default parameter:req=default
+# CHECK: ^
+
+ .macro missing_required_parameter parameter:req
+ .endm
+
+ missing_required_parameter
+
+# CHECK: error: missing value for required parameter 'parameter' in macro 'missing_required_parameter'
+# CHECK: missing_required_parameter
+# CHECK: ^
+
+ .macro missing_second_required_argument first=0 second:req
+ .endm
+
+ missing_second_required_argument
+
+# CHECK: error: missing value for required parameter 'second' in macro 'missing_second_required_argument'
+# CHECK: missing_second_required_argument
+# CHECK: ^
+
+ .macro second_third_required first=0 second:req third:req
+ .endm
+
+ second_third_required 0
+
+# CHECK: error: missing value for required parameter 'second' in macro 'second_third_required'
+# CHECK: second_third_required 0
+# CHECK: ^
+
+# CHECK: error: missing value for required parameter 'third' in macro 'second_third_required'
+# CHECK: second_third_required 0
+# CHECK: ^
+
+ second_third_required third=3 first=1
+
+# CHECK: error: missing value for required parameter 'second' in macro 'second_third_required'
+# CHECK: second_third_required third=3 first=1
+# CHECK: ^
+
diff --git a/test/MC/AsmParser/macro-qualifier.s b/test/MC/AsmParser/macro-qualifier.s
new file mode 100644
index 0000000000..7714e5cfa9
--- /dev/null
+++ b/test/MC/AsmParser/macro-qualifier.s
@@ -0,0 +1,16 @@
+# RUN: llvm-mc -triple i386 -o - %s | FileCheck %s
+
+ .macro required parameter:req
+ .long \parameter
+ .endm
+
+ required 0
+# CHECK: .long 0
+
+ .macro required_with_default parameter:req=0
+ .long \parameter
+ .endm
+
+ required 1
+# CHECK: .long 1
+