IsClassOrFunction: Handle signedness modifiers
When using these modifiers, a type can consist of multiple tokens as for example "unsigned int". However the keyword "int" can also be omitted, making "unsigned" itself also a valid type. Note that this only handles the most basic case for the modifiers. The size modifiers "short", "long", and "long long" would need similar treatment. Moreover the standard permits any order for the type specifiers, ie "unsigned long long int" and "long int unsigned long" are both valid (and actually the same type).
This commit is contained in:
parent
8b34a4ce85
commit
f2b3a8408e
@ -60,6 +60,31 @@ class MinimalPPLexer: public Lexer {
|
|||||||
return llvm::StringRef();
|
return llvm::StringRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Skip an identifier of a function.
|
||||||
|
bool SkipIdentifier(Token& Tok) {
|
||||||
|
if (Tok.isNot(tok::raw_identifier)) {
|
||||||
|
// If we're not at an identifier, we might be still be in return value:
|
||||||
|
// A::B::C funcname() or int * funcname()
|
||||||
|
if (!SkipScopes(Tok))
|
||||||
|
return false;
|
||||||
|
if (!SkipPointerRefs(Tok))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function or class name should be in Tok now
|
||||||
|
if (Identifier(Tok).empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Advance to argument list or method name
|
||||||
|
if (!LexClean(Tok))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!SkipScopes(Tok))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
///\brief Construct a Lexer from LangOpts and source.
|
///\brief Construct a Lexer from LangOpts and source.
|
||||||
MinimalPPLexer(const LangOptions &LangOpts, llvm::StringRef source):
|
MinimalPPLexer(const LangOptions &LangOpts, llvm::StringRef source):
|
||||||
@ -204,6 +229,7 @@ public:
|
|||||||
Ctor = false;
|
Ctor = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
bool SeenSignedness = false;
|
||||||
if (First.equals("struct") || First.equals("class")) {
|
if (First.equals("struct") || First.equals("class")) {
|
||||||
do {
|
do {
|
||||||
// Identifier(Tok).empty() is redundant 1st time, but simplifies code
|
// Identifier(Tok).empty() is redundant 1st time, but simplifies code
|
||||||
@ -220,29 +246,24 @@ public:
|
|||||||
|
|
||||||
} else if (First.equals("static") || First.equals("constexpr") ||
|
} else if (First.equals("static") || First.equals("constexpr") ||
|
||||||
First.equals("inline") || First.equals("const")) {
|
First.equals("inline") || First.equals("const")) {
|
||||||
|
// First check if the current keyword is "unsigned".
|
||||||
|
llvm::StringRef Modifier = Identifier(Tok);
|
||||||
|
if (Modifier.equals("signed") || Modifier.equals("unsigned"))
|
||||||
|
SeenSignedness = true;
|
||||||
|
|
||||||
// Advance past keyword for below
|
// Advance past keyword for below
|
||||||
if (!LexClean(Tok))
|
if (!LexClean(Tok))
|
||||||
return kNONE;
|
return kNONE;
|
||||||
|
} else if (First.equals("signed") || First.equals("unsigned")) {
|
||||||
|
SeenSignedness = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Tok.isNot(tok::raw_identifier)) {
|
if (!SkipIdentifier(Tok))
|
||||||
// If we're not at an identifier, we might be still be in return value:
|
|
||||||
// A::B::C funcname() or int * funcname()
|
|
||||||
if (!SkipScopes(Tok))
|
|
||||||
return kNONE;
|
|
||||||
if (!SkipPointerRefs(Tok))
|
|
||||||
return kNONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function or class name should be in Tok now
|
|
||||||
if (Identifier(Tok).empty())
|
|
||||||
return kNONE;
|
return kNONE;
|
||||||
|
|
||||||
// Advance to argument list or method name
|
// If we have not yet reached the argument list and seen a signedness
|
||||||
if (!LexClean(Tok))
|
// modifier keyword, try to skip this once.
|
||||||
return kNONE;
|
if (SeenSignedness && Tok.isNot(tok::l_paren) && !SkipIdentifier(Tok))
|
||||||
|
|
||||||
if (!SkipScopes(Tok))
|
|
||||||
return kNONE;
|
return kNONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +59,45 @@ localFun(0)
|
|||||||
localFun(5, 6, 7)
|
localFun(5, 6, 7)
|
||||||
// CHECK: localFun(5, 6, 7)
|
// CHECK: localFun(5, 6, 7)
|
||||||
// CHECK: (int) 3
|
// CHECK: (int) 3
|
||||||
|
|
||||||
|
|
||||||
|
unsigned uFun(int a) {
|
||||||
|
printf("uFun(%d)\n", a);
|
||||||
|
return 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int uiFun(int a, int b) {
|
||||||
|
printf("uiFun(%d, %d)\n", a, b);
|
||||||
|
return 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
uFun(6)
|
||||||
|
// CHECK: uFun(6)
|
||||||
|
// CHECK: (unsigned int) 7
|
||||||
|
|
||||||
|
uiFun(7, 8)
|
||||||
|
// CHECK: uiFun(7, 8)
|
||||||
|
// CHECK: (unsigned int) 9
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned suFun(int a) {
|
||||||
|
printf("suFun(%d)\n", a);
|
||||||
|
return 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int suiFun(int a, int b) {
|
||||||
|
printf("suiFun(%d, %d)\n", a, b);
|
||||||
|
return 13;
|
||||||
|
}
|
||||||
|
|
||||||
|
suFun(10)
|
||||||
|
// CHECK: suFun(10)
|
||||||
|
// CHECK: (unsigned int) 11
|
||||||
|
|
||||||
|
suiFun(11, 12)
|
||||||
|
// CHECK: suiFun(11, 12)
|
||||||
|
// CHECK: (unsigned int) 13
|
||||||
|
|
||||||
|
|
||||||
class Test {
|
class Test {
|
||||||
public:
|
public:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user