Skip to content

Commit 8a77b45

Browse files
committed
[ObjC] Handle @import directive as a pp-directive
Signed-off-by: Wang, Yihan <[email protected]>
1 parent 5dc3c9a commit 8a77b45

File tree

14 files changed

+182
-192
lines changed

14 files changed

+182
-192
lines changed

clang/examples/AnnotateFunctions/AnnotateFunctions.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class PragmaAnnotateHandler : public PragmaHandler {
6565
Token Tok;
6666
PP.LexUnexpandedToken(Tok);
6767
if (Tok.isNot(tok::eod))
68-
PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma";
68+
PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "#pragma";
6969

7070
if (HandledDecl) {
7171
DiagnosticsEngine &D = PP.getDiagnostics();

clang/include/clang/Basic/DiagnosticLexKinds.td

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -465,10 +465,7 @@ def err_pp_embed_device_file : Error<
465465
"device files are not yet supported by '#embed' directive">;
466466

467467
def ext_pp_extra_tokens_at_eol : ExtWarn<
468-
"extra tokens at end of #%0 directive">, InGroup<ExtraTokens>;
469-
def ext_pp_extra_tokens_at_module_directive_eol
470-
: ExtWarn<"extra tokens at end of '%0' directive">,
471-
InGroup<ExtraTokens>;
468+
"extra tokens at end of %0 directive">, InGroup<ExtraTokens>;
472469

473470
def ext_pp_comma_expr : Extension<"comma operator in operand of #if">;
474471
def ext_pp_bad_vaargs_use : Extension<

clang/include/clang/Lex/Preprocessor.h

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -137,24 +137,6 @@ struct CXXStandardLibraryVersionInfo {
137137
std::uint64_t Version;
138138
};
139139

140-
class ExportContextualKeywordInfo {
141-
Token ExportTok;
142-
bool AtPhysicalStartOfLine = false;
143-
144-
public:
145-
ExportContextualKeywordInfo() = default;
146-
ExportContextualKeywordInfo(const Token &Tok, bool AtPhysicalStartOfLine)
147-
: ExportTok(Tok), AtPhysicalStartOfLine(AtPhysicalStartOfLine) {}
148-
149-
bool isValid() const { return ExportTok.is(tok::kw_export); }
150-
bool isAtPhysicalStartOfLine() const { return AtPhysicalStartOfLine; }
151-
Token getExportTok() const { return ExportTok; }
152-
void reset() {
153-
ExportTok.startToken();
154-
AtPhysicalStartOfLine = false;
155-
}
156-
};
157-
158140
/// Engages in a tight little dance with the lexer to efficiently
159141
/// preprocess tokens.
160142
///
@@ -378,7 +360,7 @@ class Preprocessor {
378360
bool DeclaringCXXNamedModules = false;
379361

380362
/// Whether the last token we lexed was an 'export' keyword.
381-
ExportContextualKeywordInfo LastTokenWasExportKeyword;
363+
std::optional<Token> ModuleLikeDirectiveIntroducer;
382364

383365
/// First pp-token source location in current translation unit.
384366
SourceLocation FirstPPTokenLoc;
@@ -1808,15 +1790,15 @@ class Preprocessor {
18081790
void EnterModuleSuffixTokenStream(ArrayRef<Token> Toks);
18091791
void HandleCXXImportDirective(Token Import);
18101792
void HandleCXXModuleDirective(Token Module);
1793+
void HandleObjCAtImportDirective(Token &ImportTok);
18111794

18121795
/// Callback invoked when the lexer sees one of export, import or module token
18131796
/// at the start of a line.
18141797
///
18151798
/// This consumes the import/module directive, modifies the
18161799
/// lexer/preprocessor state, and advances the lexer(s) so that the next token
18171800
/// read is the correct one.
1818-
bool HandleModuleContextualKeyword(Token &Result,
1819-
bool TokAtPhysicalStartOfLine);
1801+
bool HandleModuleContextualKeyword(Token &Result);
18201802

18211803
/// Get the start location of the first pp-token in main file.
18221804
SourceLocation getMainFileFirstPPTokenLoc() const {
@@ -1825,7 +1807,6 @@ class Preprocessor {
18251807
return FirstPPTokenLoc;
18261808
}
18271809

1828-
bool LexAfterModuleImport(Token &Result);
18291810
void CollectPPImportSuffix(SmallVectorImpl<Token> &Toks,
18301811
bool StopUntilEOD = false);
18311812
bool CollectPPImportSuffixAndEnterStream(SmallVectorImpl<Token> &Toks,
@@ -2356,6 +2337,7 @@ class Preprocessor {
23562337
template <typename... Ts> bool isNextPPTokenOneOf(Ts... Ks) {
23572338
static_assert(sizeof...(Ts) > 0,
23582339
"requires at least one tok::TokenKind specified");
2340+
23592341
// Do some quick tests for rejection cases.
23602342
std::optional<Token> Val;
23612343
if (CurLexer)
@@ -3175,9 +3157,6 @@ class Preprocessor {
31753157
static bool CLK_DependencyDirectivesLexer(Preprocessor &P, Token &Result) {
31763158
return P.CurLexer->LexDependencyDirectiveToken(Result);
31773159
}
3178-
static bool CLK_LexAfterModuleImport(Preprocessor &P, Token &Result) {
3179-
return P.LexAfterModuleImport(Result);
3180-
}
31813160
};
31823161

31833162
/// Abstract base class that describes a handler that will receive

clang/include/clang/Lex/Token.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,10 @@ class Token {
9090
// re-added, e.g. via EnterTokenStream. Annotation
9191
// tokens are *not* reinjected.
9292
HasSeenNoTrivialPPDirective =
93-
0x1000, // Whether we've seen any 'no-trivial' pp-directives before
93+
0x1000, // Whether we've seen any 'no-trivial' pp-directives before//
9494
// current position.
95+
PhysicalStartOfLine =
96+
0x2000, // At the physical start of line or only after whitespace.
9597
};
9698

9799
tok::TokenKind getKind() const { return Kind; }
@@ -277,6 +279,10 @@ class Token {
277279
///
278280
bool isAtStartOfLine() const { return getFlag(StartOfLine); }
279281

282+
/// isAtPhysicalStartOfLine - Return true if this token is at the physical
283+
/// start of a line.
284+
bool isAtPhysicalStartOfLine() const { return getFlag(PhysicalStartOfLine); }
285+
280286
/// Return true if this token has whitespace before it.
281287
///
282288
bool hasLeadingSpace() const { return getFlag(LeadingSpace); }

clang/lib/Lex/DependencyDirectivesScanner.cpp

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -579,15 +579,12 @@ bool Scanner::lexModuleDirectiveBody(DirectiveKind Kind, const char *&First,
579579
return false;
580580
}
581581

582+
const auto &Tok = lexToken(First, End);
582583
pushDirective(Kind);
583-
skipWhitespace(First, End);
584-
if (First == End)
584+
if (Tok.is(tok::eof) || Tok.is(tok::eod))
585585
return false;
586-
if (!isVerticalWhitespace(*First))
587-
return reportError(
588-
DirectiveLoc, diag::err_dep_source_scanner_unexpected_tokens_at_import);
589-
skipNewline(First, End);
590-
return false;
586+
return reportError(DirectiveLoc,
587+
diag::err_dep_source_scanner_unexpected_tokens_at_import);
591588
}
592589

593590
dependency_directives_scan::Token &Scanner::lexToken(const char *&First,
@@ -931,10 +928,6 @@ bool Scanner::lexPPLine(const char *&First, const char *const End) {
931928
CurDirToks.clear();
932929
});
933930

934-
// FIXME: Shoule we handle @import as a preprocessing directive?
935-
if (*First == '@')
936-
return lexAt(First, End);
937-
938931
if (*First == '_') {
939932
if (isNextIdentifierOrSkipLine("_Pragma", First, End))
940933
return lex_Pragma(First, End);
@@ -947,6 +940,10 @@ bool Scanner::lexPPLine(const char *&First, const char *const End) {
947940
auto ScEx2 = make_scope_exit(
948941
[&]() { TheLexer.setParsingPreprocessorDirective(false); });
949942

943+
// FIXME: Shoule we handle @import as a preprocessing directive?
944+
if (*First == '@')
945+
return lexAt(First, End);
946+
950947
// Handle module directives for C++20 modules.
951948
if (*First == 'i' || *First == 'e' || *First == 'm')
952949
return lexModule(First, End);

clang/lib/Lex/Lexer.cpp

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -77,16 +77,13 @@ tok::ObjCKeywordKind Token::getObjCKeywordID() const {
7777
/// or module).
7878
bool Token::isModuleContextualKeyword(const LangOptions &LangOpts,
7979
bool AllowExport) const {
80-
if (!LangOpts.CPlusPlusModules)
80+
if (!LangOpts.CPlusPlusModules || isAnnotation())
8181
return false;
8282
if (AllowExport && is(tok::kw_export))
8383
return true;
84-
if (isOneOf(tok::kw_import, tok::kw_module))
85-
return true;
86-
if (isNot(tok::identifier))
87-
return false;
88-
const auto *II = getIdentifierInfo();
89-
return II->isModulesImport() || II->isModulesDeclaration();
84+
if (const auto *II = getIdentifierInfo())
85+
return II->isModulesImport() || II->isModulesDeclaration();
86+
return false;
9087
}
9188

9289
/// Determine whether the token kind starts a simple-type-specifier.
@@ -3758,6 +3755,9 @@ bool Lexer::LexTokenInternal(Token &Result, bool TokAtPhysicalStartOfLine) {
37583755
assert(!Result.needsCleaning() && "Result needs cleaning");
37593756
assert(!Result.hasPtrData() && "Result has not been reset");
37603757

3758+
if (TokAtPhysicalStartOfLine)
3759+
Result.setFlag(Token::PhysicalStartOfLine);
3760+
37613761
// CurPtr - Cache BufferPtr in an automatic variable.
37623762
const char *CurPtr = BufferPtr;
37633763

@@ -4040,10 +4040,9 @@ bool Lexer::LexTokenInternal(Token &Result, bool TokAtPhysicalStartOfLine) {
40404040
// Notify MIOpt that we read a non-whitespace/non-comment token.
40414041
MIOpt.ReadToken();
40424042
bool returnedToken = LexIdentifierContinue(Result, CurPtr);
4043-
if (returnedToken && Result.isModuleContextualKeyword(LangOpts) &&
4044-
!LexingRawMode && !Is_PragmaLexer && !ParsingPreprocessorDirective &&
4045-
PP &&
4046-
PP->HandleModuleContextualKeyword(Result, TokAtPhysicalStartOfLine))
4043+
if (returnedToken && Result.isNot(tok::eof) && !LexingRawMode &&
4044+
!Is_PragmaLexer && !ParsingPreprocessorDirective && PP &&
4045+
PP->HandleModuleContextualKeyword(Result))
40474046
goto HandleDirective;
40484047
return returnedToken;
40494048
}
@@ -4454,9 +4453,14 @@ bool Lexer::LexTokenInternal(Token &Result, bool TokAtPhysicalStartOfLine) {
44544453

44554454
case '@':
44564455
// Objective C support.
4457-
if (CurPtr[-1] == '@' && LangOpts.ObjC)
4456+
if (CurPtr[-1] == '@' && LangOpts.ObjC) {
4457+
if (TokAtPhysicalStartOfLine && !LexingRawMode && !Is_PragmaLexer) {
4458+
FormTokenWithChars(Result, CurPtr, tok::at);
4459+
(void)PP->HandleModuleContextualKeyword(Result);
4460+
return true;
4461+
}
44584462
Kind = tok::at;
4459-
else
4463+
} else
44604464
Kind = tok::unknown;
44614465
break;
44624466

@@ -4538,10 +4542,6 @@ bool Lexer::LexTokenInternal(Token &Result, bool TokAtPhysicalStartOfLine) {
45384542
HandleDirective:
45394543
PP->HandleDirective(Result);
45404544

4541-
if (PP->hadModuleLoaderFatalFailure())
4542-
// With a fatal failure in the module loader, we abort parsing.
4543-
return true;
4544-
45454545
// We parsed the directive; lex a token with the new state.
45464546
return false;
45474547

@@ -4608,20 +4608,26 @@ bool Lexer::LexDependencyDirectiveToken(Token &Result) {
46084608

46094609
const char *TokPtr = convertDependencyDirectiveToken(DDTok, Result);
46104610

4611-
if (Result.is(tok::hash) && Result.isAtStartOfLine()) {
4611+
if (Result.is(tok::hash) && Result.isAtStartOfLine() && !isLexingRawMode()) {
46124612
PP->HandleDirective(Result);
46134613
if (PP->hadModuleLoaderFatalFailure())
46144614
// With a fatal failure in the module loader, we abort parsing.
46154615
return true;
46164616
return false;
46174617
}
4618+
if (Result.is(tok::at) && Result.isAtStartOfLine() && !isLexingRawMode()) {
4619+
(void)PP->HandleModuleContextualKeyword(Result);
4620+
return false;
4621+
}
46184622
if (Result.is(tok::raw_identifier)) {
46194623
Result.setRawIdentifierData(TokPtr);
46204624
if (!isLexingRawMode()) {
46214625
const IdentifierInfo *II = PP->LookUpIdentifierInfo(Result);
4622-
if (Result.isModuleContextualKeyword(LangOpts) &&
4623-
PP->HandleModuleContextualKeyword(Result, Result.isAtStartOfLine())) {
4626+
if (PP->HandleModuleContextualKeyword(Result)) {
46244627
PP->HandleDirective(Result);
4628+
if (PP->hadModuleLoaderFatalFailure())
4629+
// With a fatal failure in the module loader, we abort parsing.
4630+
return true;
46254631
return false;
46264632
}
46274633
if (II->isHandleIdentifierCase())

0 commit comments

Comments
 (0)