forked from OSchip/llvm-project
Implement the MS extension __identifier properly: take a token and strip it of
its keywordliness. llvm-svn: 203987
This commit is contained in:
parent
cec949af13
commit
ae385084c5
|
@ -403,6 +403,9 @@ def warn_has_warning_invalid_option :
|
|||
ExtWarn<"__has_warning expected option name (e.g. \"-Wundef\")">,
|
||||
InGroup<MalformedWarningCheck>;
|
||||
|
||||
def err_pp_identifier_arg_not_identifier : Error<
|
||||
"cannot convert %0 token to an identifier">;
|
||||
|
||||
def warn_pragma_include_alias_mismatch_angle :
|
||||
ExtWarn<"angle-bracketed include <%0> cannot be aliased to double-quoted "
|
||||
"include \"%1\"">, InGroup<UnknownPragmas>;
|
||||
|
|
|
@ -116,6 +116,7 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
|
|||
IdentifierInfo *Ident__TIMESTAMP__; // __TIMESTAMP__
|
||||
IdentifierInfo *Ident__COUNTER__; // __COUNTER__
|
||||
IdentifierInfo *Ident_Pragma, *Ident__pragma; // _Pragma, __pragma
|
||||
IdentifierInfo *Ident__identifier; // __identifier
|
||||
IdentifierInfo *Ident__VA_ARGS__; // __VA_ARGS__
|
||||
IdentifierInfo *Ident__has_feature; // __has_feature
|
||||
IdentifierInfo *Ident__has_extension; // __has_extension
|
||||
|
|
|
@ -517,10 +517,6 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
|
|||
Builder.defineMacro("_WCHAR_T_DEFINED");
|
||||
Builder.defineMacro("_NATIVE_WCHAR_T_DEFINED");
|
||||
}
|
||||
if (LangOpts.CPlusPlus) {
|
||||
// FIXME: Support Microsoft's __identifier extension in the lexer.
|
||||
Builder.append("#define __identifier(x) x");
|
||||
}
|
||||
}
|
||||
|
||||
if (LangOpts.Optimize)
|
||||
|
|
|
@ -97,6 +97,15 @@ void Preprocessor::RegisterBuiltinMacros() {
|
|||
Ident__INCLUDE_LEVEL__ = RegisterBuiltinMacro(*this, "__INCLUDE_LEVEL__");
|
||||
Ident__TIMESTAMP__ = RegisterBuiltinMacro(*this, "__TIMESTAMP__");
|
||||
|
||||
// Microsoft Extensions.
|
||||
if (LangOpts.MicrosoftExt) {
|
||||
Ident__identifier = RegisterBuiltinMacro(*this, "__identifier");
|
||||
Ident__pragma = RegisterBuiltinMacro(*this, "__pragma");
|
||||
} else {
|
||||
Ident__identifier = 0;
|
||||
Ident__pragma = 0;
|
||||
}
|
||||
|
||||
// Clang Extensions.
|
||||
Ident__has_feature = RegisterBuiltinMacro(*this, "__has_feature");
|
||||
Ident__has_extension = RegisterBuiltinMacro(*this, "__has_extension");
|
||||
|
@ -119,12 +128,6 @@ void Preprocessor::RegisterBuiltinMacros() {
|
|||
Ident__building_module = 0;
|
||||
Ident__MODULE__ = 0;
|
||||
}
|
||||
|
||||
// Microsoft Extensions.
|
||||
if (LangOpts.MicrosoftExt)
|
||||
Ident__pragma = RegisterBuiltinMacro(*this, "__pragma");
|
||||
else
|
||||
Ident__pragma = 0;
|
||||
}
|
||||
|
||||
/// isTrivialSingleTokenExpansion - Return true if MI, which has a single token
|
||||
|
@ -1481,6 +1484,44 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
|
|||
IdentifierInfo *ModuleII = getIdentifierInfo(getLangOpts().CurrentModule);
|
||||
Tok.setIdentifierInfo(ModuleII);
|
||||
Tok.setKind(ModuleII->getTokenID());
|
||||
} else if (II == Ident__identifier) {
|
||||
SourceLocation Loc = Tok.getLocation();
|
||||
|
||||
// We're expecting '__identifier' '(' identifier ')'. Try to recover
|
||||
// if the parens are missing.
|
||||
LexNonComment(Tok);
|
||||
if (Tok.isNot(tok::l_paren)) {
|
||||
// No '(', use end of last token.
|
||||
Diag(getLocForEndOfToken(Loc), diag::err_pp_expected_after)
|
||||
<< II << tok::l_paren;
|
||||
// If the next token isn't valid as our argument, we can't recover.
|
||||
if (!Tok.isAnnotation() && Tok.getIdentifierInfo())
|
||||
Tok.setKind(tok::identifier);
|
||||
return;
|
||||
}
|
||||
|
||||
SourceLocation LParenLoc = Tok.getLocation();
|
||||
LexNonComment(Tok);
|
||||
|
||||
if (!Tok.isAnnotation() && Tok.getIdentifierInfo())
|
||||
Tok.setKind(tok::identifier);
|
||||
else {
|
||||
Diag(Tok.getLocation(), diag::err_pp_identifier_arg_not_identifier)
|
||||
<< Tok.getKind();
|
||||
// Don't walk past anything that's not a real token.
|
||||
if (Tok.is(tok::eof) || Tok.is(tok::eod) || Tok.isAnnotation())
|
||||
return;
|
||||
}
|
||||
|
||||
// Discard the ')', preserving 'Tok' as our result.
|
||||
Token RParen;
|
||||
LexNonComment(RParen);
|
||||
if (RParen.isNot(tok::r_paren)) {
|
||||
Diag(getLocForEndOfToken(Tok.getLocation()), diag::err_pp_expected_after)
|
||||
<< Tok.getKind() << tok::r_paren;
|
||||
Diag(LParenLoc, diag::note_matching) << tok::l_paren;
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
llvm_unreachable("Unknown identifier!");
|
||||
}
|
||||
|
|
|
@ -325,6 +325,29 @@ class IF_EXISTS_CLASS_TEST {
|
|||
|
||||
|
||||
int __identifier(generic) = 3;
|
||||
int __identifier(int) = 4;
|
||||
struct __identifier(class) { __identifier(class) *__identifier(for); };
|
||||
__identifier(class) __identifier(struct) = { &__identifier(struct) };
|
||||
|
||||
int __identifier for; // expected-error {{missing '(' after '__identifier'}}
|
||||
int __identifier(else} = __identifier(for); // expected-error {{missing ')' after identifier}} expected-note {{to match this '('}}
|
||||
#define identifier_weird(x) __identifier(x
|
||||
int k = identifier_weird(if)); // expected-error {{use of undeclared identifier 'if'}}
|
||||
|
||||
// This is a bit weird, but the alternative tokens aren't keywords, and this
|
||||
// behavior matches MSVC. FIXME: Consider supporting this anyway.
|
||||
extern int __identifier(and) r; // expected-error {{cannot convert '&&' token to an identifier}}
|
||||
|
||||
void f() {
|
||||
__identifier(() // expected-error {{cannot convert '(' token to an identifier}}
|
||||
__identifier(void) // expected-error {{use of undeclared identifier 'void'}}
|
||||
__identifier()) // expected-error {{cannot convert ')' token to an identifier}}
|
||||
// FIXME: We should pick a friendlier display name for this token kind.
|
||||
__identifier(1) // expected-error {{cannot convert <numeric_constant> token to an identifier}}
|
||||
__identifier(+) // expected-error {{cannot convert '+' token to an identifier}}
|
||||
__identifier("foo") // expected-error {{cannot convert <string_literal> token to an identifier}}
|
||||
__identifier(;) // expected-error {{cannot convert ';' token to an identifier}}
|
||||
}
|
||||
|
||||
class inline_definition_pure_spec {
|
||||
virtual int f() = 0 { return 0; }// expected-warning {{function definition with pure-specifier is a Microsoft extension}}
|
||||
|
|
Loading…
Reference in New Issue