mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-04-17 22:00:41 +00:00
Add pragma to perform module import and use it in -E output.
Many of our supported configurations support modules but do not have any first-class syntax to perform a module import. This leaves us with a problem: there is no way to represent the expansion of a #include that imports a module in the -E output for such languages. (We don't want to just leave it as a #include because that requires the consumer of the preprocessed source to have the same file system layout and include paths as the creator.) This patch adds a new pragma: #pragma clang module import MODULE.NAME.HERE that imports a module, and changes -E and -frewrite-includes to use it when rewriting a #include that maps to a module import. We don't make any attempt to use a native language syntax import if one exists, to get more consistent output. (If in the future, @import and #include have different semantics in some way, the pragma will track the #include semantics.) llvm-svn: 301725
This commit is contained in:
parent
6fdcb3c2ce
commit
c51c38b4ec
@ -475,6 +475,8 @@ def warn_pragma_pop_macro_no_push : Warning<
|
||||
def warn_pragma_message : Warning<"%0">,
|
||||
InGroup<PoundPragmaMessage>, DefaultWarnNoWerror;
|
||||
def err_pragma_message : Error<"%0">;
|
||||
def err_pragma_module_import_expected_module_name : Error<
|
||||
"expected %select{identifier in|'.' or end of directive after}0 module name">;
|
||||
def warn_pragma_ignored : Warning<"unknown pragma ignored">,
|
||||
InGroup<UnknownPragmas>, DefaultIgnore;
|
||||
def ext_stdc_pragma_ignored : ExtWarn<"unknown pragma in STDC namespace">,
|
||||
|
@ -1263,6 +1263,10 @@ public:
|
||||
CachedTokens[CachedLexPos-1] = Tok;
|
||||
}
|
||||
|
||||
/// Enter an annotation token into the token stream.
|
||||
void EnterAnnotationToken(SourceRange Range, tok::TokenKind Kind,
|
||||
void *AnnotationVal);
|
||||
|
||||
/// Update the current token to represent the provided
|
||||
/// identifier, in order to cache an action performed by typo correction.
|
||||
void TypoCorrectToken(const Token &Tok) {
|
||||
@ -1963,6 +1967,7 @@ public:
|
||||
void HandlePragmaPoison();
|
||||
void HandlePragmaSystemHeader(Token &SysHeaderTok);
|
||||
void HandlePragmaDependency(Token &DependencyTok);
|
||||
void HandlePragmaModuleImport(Token &Tok);
|
||||
void HandlePragmaPushMacro(Token &Tok);
|
||||
void HandlePragmaPopMacro(Token &Tok);
|
||||
void HandlePragmaIncludeAlias(Token &Tok);
|
||||
|
@ -324,43 +324,50 @@ void PrintPPOutputPPCallbacks::InclusionDirective(SourceLocation HashLoc,
|
||||
StringRef SearchPath,
|
||||
StringRef RelativePath,
|
||||
const Module *Imported) {
|
||||
if (Imported) {
|
||||
// When preprocessing, turn implicit imports into @imports.
|
||||
// FIXME: This is a stop-gap until a more comprehensive "preprocessing with
|
||||
// modules" solution is introduced.
|
||||
// In -dI mode, dump #include directives prior to dumping their content or
|
||||
// interpretation.
|
||||
if (DumpIncludeDirectives) {
|
||||
startNewLineIfNeeded();
|
||||
MoveToLine(HashLoc);
|
||||
if (PP.getLangOpts().ObjC2) {
|
||||
OS << "@import " << Imported->getFullModuleName() << ";"
|
||||
<< " /* clang -E: implicit import for \"" << File->getName()
|
||||
<< "\" */";
|
||||
} else {
|
||||
const std::string TokenText = PP.getSpelling(IncludeTok);
|
||||
assert(!TokenText.empty());
|
||||
OS << "#" << TokenText << " "
|
||||
<< (IsAngled ? '<' : '"')
|
||||
<< FileName
|
||||
<< (IsAngled ? '>' : '"')
|
||||
<< " /* clang -E: implicit import for module "
|
||||
<< Imported->getFullModuleName() << " */";
|
||||
}
|
||||
// Since we want a newline after the @import, but not a #<line>, start a new
|
||||
// line immediately.
|
||||
EmittedTokensOnThisLine = true;
|
||||
const std::string TokenText = PP.getSpelling(IncludeTok);
|
||||
assert(!TokenText.empty());
|
||||
OS << "#" << TokenText << " "
|
||||
<< (IsAngled ? '<' : '"') << FileName << (IsAngled ? '>' : '"')
|
||||
<< " /* clang -E -dI */";
|
||||
setEmittedDirectiveOnThisLine();
|
||||
startNewLineIfNeeded();
|
||||
} else {
|
||||
// Not a module import; it's a more vanilla inclusion of some file using one
|
||||
// of: #include, #import, #include_next, #include_macros.
|
||||
if (DumpIncludeDirectives) {
|
||||
}
|
||||
|
||||
// When preprocessing, turn implicit imports into module import pragmas.
|
||||
if (Imported) {
|
||||
switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) {
|
||||
case tok::pp_include:
|
||||
case tok::pp_import:
|
||||
case tok::pp_include_next:
|
||||
startNewLineIfNeeded();
|
||||
MoveToLine(HashLoc);
|
||||
const std::string TokenText = PP.getSpelling(IncludeTok);
|
||||
assert(!TokenText.empty());
|
||||
OS << "#" << TokenText << " "
|
||||
OS << "#pragma clang module import " << Imported->getFullModuleName()
|
||||
<< " /* clang -E: implicit import for "
|
||||
<< "#" << PP.getSpelling(IncludeTok) << " "
|
||||
<< (IsAngled ? '<' : '"') << FileName << (IsAngled ? '>' : '"')
|
||||
<< " /* clang -E -dI */";
|
||||
setEmittedDirectiveOnThisLine();
|
||||
<< " */";
|
||||
// Since we want a newline after the pragma, but not a #<line>, start a
|
||||
// new line immediately.
|
||||
EmittedTokensOnThisLine = true;
|
||||
startNewLineIfNeeded();
|
||||
break;
|
||||
|
||||
case tok::pp___include_macros:
|
||||
// #__include_macros has no effect on a user of a preprocessed source
|
||||
// file; the only effect is on preprocessing.
|
||||
//
|
||||
// FIXME: That's not *quite* true: it causes the module in question to
|
||||
// be loaded, which can affect downstream diagnostics.
|
||||
break;
|
||||
|
||||
default:
|
||||
llvm_unreachable("unknown include directive kind");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ void InclusionRewriter::WriteLineInfo(StringRef Filename, int Line,
|
||||
}
|
||||
|
||||
void InclusionRewriter::WriteImplicitModuleImport(const Module *Mod) {
|
||||
OS << "@import " << Mod->getFullModuleName() << ";"
|
||||
OS << "#pragma clang module import " << Mod->getFullModuleName()
|
||||
<< " /* clang -frewrite-includes: implicit import */" << MainEOL;
|
||||
}
|
||||
|
||||
@ -450,9 +450,7 @@ bool InclusionRewriter::Process(FileID FileId,
|
||||
WriteLineInfo(FileName, Line - 1, FileType, "");
|
||||
StringRef LineInfoExtra;
|
||||
SourceLocation Loc = HashToken.getLocation();
|
||||
if (const Module *Mod = PP.getLangOpts().ObjC2
|
||||
? FindModuleAtLocation(Loc)
|
||||
: nullptr)
|
||||
if (const Module *Mod = FindModuleAtLocation(Loc))
|
||||
WriteImplicitModuleImport(Mod);
|
||||
else if (const IncludedFile *Inc = FindIncludeAtLocation(Loc)) {
|
||||
// include and recursively process the file
|
||||
|
@ -1588,18 +1588,18 @@ bool Preprocessor::ConcatenateIncludeName(SmallString<128> &FilenameBuffer,
|
||||
}
|
||||
|
||||
/// \brief Push a token onto the token stream containing an annotation.
|
||||
static void EnterAnnotationToken(Preprocessor &PP,
|
||||
SourceLocation Begin, SourceLocation End,
|
||||
tok::TokenKind Kind, void *AnnotationVal) {
|
||||
void Preprocessor::EnterAnnotationToken(SourceRange Range,
|
||||
tok::TokenKind Kind,
|
||||
void *AnnotationVal) {
|
||||
// FIXME: Produce this as the current token directly, rather than
|
||||
// allocating a new token for it.
|
||||
auto Tok = llvm::make_unique<Token[]>(1);
|
||||
Tok[0].startToken();
|
||||
Tok[0].setKind(Kind);
|
||||
Tok[0].setLocation(Begin);
|
||||
Tok[0].setAnnotationEndLoc(End);
|
||||
Tok[0].setLocation(Range.getBegin());
|
||||
Tok[0].setAnnotationEndLoc(Range.getEnd());
|
||||
Tok[0].setAnnotationValue(AnnotationVal);
|
||||
PP.EnterTokenStream(std::move(Tok), 1, true);
|
||||
EnterTokenStream(std::move(Tok), 1, true);
|
||||
}
|
||||
|
||||
/// \brief Produce a diagnostic informing the user that a #include or similar
|
||||
@ -2021,7 +2021,8 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
|
||||
|
||||
if (IncludeTok.getIdentifierInfo()->getPPKeywordID() !=
|
||||
tok::pp___include_macros)
|
||||
EnterAnnotationToken(*this, HashLoc, End, tok::annot_module_include, M);
|
||||
EnterAnnotationToken(SourceRange(HashLoc, End),
|
||||
tok::annot_module_include, M);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -2059,7 +2060,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
|
||||
// submodule.
|
||||
// FIXME: There's no point doing this if we're handling a #__include_macros
|
||||
// directive.
|
||||
EnterAnnotationToken(*this, HashLoc, End, tok::annot_module_begin, M);
|
||||
EnterAnnotationToken(SourceRange(HashLoc, End), tok::annot_module_begin, M);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -534,6 +534,47 @@ void Preprocessor::HandlePragmaDependency(Token &DependencyTok) {
|
||||
}
|
||||
}
|
||||
|
||||
void Preprocessor::HandlePragmaModuleImport(Token &ImportTok) {
|
||||
SourceLocation ImportLoc = ImportTok.getLocation();
|
||||
|
||||
Token Tok;
|
||||
|
||||
llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 8> ModuleName;
|
||||
while (true) {
|
||||
LexUnexpandedToken(Tok);
|
||||
if (Tok.isNot(tok::identifier)) {
|
||||
Diag(Tok.getLocation(),
|
||||
diag::err_pragma_module_import_expected_module_name) << 0;
|
||||
return;
|
||||
}
|
||||
|
||||
ModuleName.emplace_back(Tok.getIdentifierInfo(), Tok.getLocation());
|
||||
|
||||
LexUnexpandedToken(Tok);
|
||||
assert(Tok.isNot(tok::eof));
|
||||
if (Tok.is(tok::eod))
|
||||
break;
|
||||
if (Tok.isNot(tok::period)) {
|
||||
Diag(Tok.getLocation(),
|
||||
diag::err_pragma_module_import_expected_module_name) << 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a non-empty module path, load the named module.
|
||||
Module *Imported =
|
||||
TheModuleLoader.loadModule(ImportLoc, ModuleName, Module::Hidden,
|
||||
/*IsIncludeDirective=*/false);
|
||||
if (!Imported)
|
||||
return;
|
||||
|
||||
makeModuleVisible(Imported, ImportLoc);
|
||||
EnterAnnotationToken(SourceRange(ImportLoc, Tok.getLocation()),
|
||||
tok::annot_module_include, Imported);
|
||||
if (Callbacks)
|
||||
Callbacks->moduleImport(ImportLoc, ModuleName, Imported);
|
||||
}
|
||||
|
||||
/// ParsePragmaPushOrPopMacro - Handle parsing of pragma push_macro/pop_macro.
|
||||
/// Return the IdentifierInfo* associated with the macro to push or pop.
|
||||
IdentifierInfo *Preprocessor::ParsePragmaPushOrPopMacro(Token &Tok) {
|
||||
@ -1301,6 +1342,19 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/// Handle the clang \#pragma module import extension. The syntax is:
|
||||
/// \code
|
||||
/// #pragma clang module import some.module.name
|
||||
/// \endcode
|
||||
struct PragmaModuleImportHandler : public PragmaHandler {
|
||||
PragmaModuleImportHandler() : PragmaHandler("import") {}
|
||||
|
||||
void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
|
||||
Token &ImportTok) override {
|
||||
PP.HandlePragmaModuleImport(ImportTok);
|
||||
}
|
||||
};
|
||||
|
||||
/// PragmaPushMacroHandler - "\#pragma push_macro" saves the value of the
|
||||
/// macro on the top of the stack.
|
||||
struct PragmaPushMacroHandler : public PragmaHandler {
|
||||
@ -1524,6 +1578,11 @@ void Preprocessor::RegisterBuiltinPragmas() {
|
||||
AddPragmaHandler("clang", new PragmaARCCFCodeAuditedHandler());
|
||||
AddPragmaHandler("clang", new PragmaAssumeNonNullHandler());
|
||||
|
||||
// #pragma clang module ...
|
||||
auto *ModuleHandler = new PragmaNamespace("module");
|
||||
AddPragmaHandler("clang", ModuleHandler);
|
||||
ModuleHandler->AddPragma(new PragmaModuleImportHandler());
|
||||
|
||||
AddPragmaHandler("STDC", new PragmaSTDC_FENV_ACCESSHandler());
|
||||
AddPragmaHandler("STDC", new PragmaSTDC_CX_LIMITED_RANGEHandler());
|
||||
AddPragmaHandler("STDC", new PragmaSTDC_UnknownHandler());
|
||||
|
@ -1,22 +1,27 @@
|
||||
// RUN: rm -rf %t
|
||||
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x objective-c %s -F %S/../Modules/Inputs -E -frewrite-includes -o - | FileCheck %s
|
||||
// RUN: mkdir %t
|
||||
// RUN: echo 'extern int dummy;' > %t/dummy.h
|
||||
// RUN: echo 'module dummy { header "dummy.h" }' > %t/module.modulemap
|
||||
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t %s -I%t -E -frewrite-includes -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x objective-c %s -I%t -E -frewrite-includes -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x c++ %s -I%t -E -frewrite-includes -o - | FileCheck %s
|
||||
|
||||
int bar();
|
||||
#include <Module/Module.h>
|
||||
#include "dummy.h"
|
||||
int foo();
|
||||
#include <Module/Module.h>
|
||||
#include "dummy.h"
|
||||
|
||||
// CHECK: int bar();{{$}}
|
||||
// CHECK-NEXT: #if 0 /* expanded by -frewrite-includes */{{$}}
|
||||
// CHECK-NEXT: #include <Module/Module.h>{{$}}
|
||||
// CHECK-NEXT: #include "dummy.h"{{$}}
|
||||
// CHECK-NEXT: #endif /* expanded by -frewrite-includes */{{$}}
|
||||
// CHECK-NEXT: # 5 "{{.*[/\\]}}rewrite-includes-modules.c"{{$}}
|
||||
// CHECK-NEXT: @import Module; /* clang -frewrite-includes: implicit import */{{$}}
|
||||
// CHECK-NEXT: # 6 "{{.*[/\\]}}rewrite-includes-modules.c"{{$}}
|
||||
// CHECK-NEXT: # 10 "{{.*[/\\]}}rewrite-includes-modules.c"{{$}}
|
||||
// CHECK-NEXT: #pragma clang module import dummy /* clang -frewrite-includes: implicit import */{{$}}
|
||||
// CHECK-NEXT: # 11 "{{.*[/\\]}}rewrite-includes-modules.c"{{$}}
|
||||
// CHECK-NEXT: int foo();{{$}}
|
||||
// CHECK-NEXT: #if 0 /* expanded by -frewrite-includes */{{$}}
|
||||
// CHECK-NEXT: #include <Module/Module.h>{{$}}
|
||||
// CHECK-NEXT: #include "dummy.h"{{$}}
|
||||
// CHECK-NEXT: #endif /* expanded by -frewrite-includes */{{$}}
|
||||
// CHECK-NEXT: # 7 "{{.*[/\\]}}rewrite-includes-modules.c"{{$}}
|
||||
// CHECK-NEXT: @import Module; /* clang -frewrite-includes: implicit import */{{$}}
|
||||
// CHECK-NEXT: # 8 "{{.*[/\\]}}rewrite-includes-modules.c"{{$}}
|
||||
// CHECK-NEXT: # 12 "{{.*[/\\]}}rewrite-includes-modules.c"{{$}}
|
||||
// CHECK-NEXT: #pragma clang module import dummy /* clang -frewrite-includes: implicit import */{{$}}
|
||||
// CHECK-NEXT: # 13 "{{.*[/\\]}}rewrite-includes-modules.c"{{$}}
|
||||
|
@ -27,7 +27,7 @@
|
||||
// CHECK-NEXT: note: diagnostic msg: {{.*}}.m
|
||||
// CHECK-NEXT: note: diagnostic msg: {{.*}}.cache
|
||||
|
||||
// CHECKSRC: @import cstd.stdio;
|
||||
// CHECKSRC: #pragma clang module import cstd.stdio
|
||||
|
||||
// CHECKSH: # Crash reproducer
|
||||
// CHECKSH-NEXT: # Driver args: "-fsyntax-only"
|
||||
|
@ -28,7 +28,7 @@
|
||||
// CHECK-NEXT: note: diagnostic msg: {{.*}}.m
|
||||
// CHECK-NEXT: note: diagnostic msg: {{.*}}.cache
|
||||
|
||||
// CHECKSRC: @import cstd.stdio;
|
||||
// CHECKSRC: #pragma clang module import cstd.stdio
|
||||
|
||||
// CHECKSH: # Crash reproducer
|
||||
// CHECKSH-NEXT: # Driver args: "-fsyntax-only"
|
||||
@ -65,4 +65,4 @@
|
||||
// RUN: -fmodules-cache-path=%t/m/ 2>&1 \
|
||||
// RUN: | FileCheck %s --check-prefix=CHECKOVERLAY
|
||||
|
||||
// CHECKOVERLAY: @import cstd.stdio; /* clang -E: implicit import for "/{{[^ ].*}}/i/usr/x/../stdio.h" */
|
||||
// CHECKOVERLAY: #pragma clang module import cstd.stdio /* clang -E: implicit import
|
||||
|
@ -29,7 +29,7 @@
|
||||
// CHECK-NEXT: note: diagnostic msg: {{.*}}.m
|
||||
// CHECK-NEXT: note: diagnostic msg: {{.*}}.cache
|
||||
|
||||
// CHECKSRC: @import cstd.stdio;
|
||||
// CHECKSRC: #pragma clang module import cstd.stdio
|
||||
|
||||
// CHECKSH: # Crash reproducer
|
||||
// CHECKSH-NEXT: # Driver args: "-fsyntax-only"
|
||||
|
@ -25,7 +25,7 @@
|
||||
// CHECK-NEXT: note: diagnostic msg: {{.*}}.m
|
||||
// CHECK-NEXT: note: diagnostic msg: {{.*}}.cache
|
||||
|
||||
// CHECKSRC: @import cstd.stdio;
|
||||
// CHECKSRC: #pragma clang module import cstd.stdio
|
||||
|
||||
// CHECKSH: # Crash reproducer
|
||||
// CHECKSH-NEXT: # Driver args: "-fsyntax-only"
|
||||
@ -62,4 +62,4 @@
|
||||
// RUN: -fmodules-cache-path=%t/m/ 2>&1 \
|
||||
// RUN: | FileCheck %s --check-prefix=CHECKOVERLAY
|
||||
|
||||
// CHECKOVERLAY: @import cstd.stdio; /* clang -E: implicit import for "/{{[^ ].*}}/usr/././//////include/../include/./././../include/stdio.h" */
|
||||
// CHECKOVERLAY: #pragma clang module import cstd.stdio /* clang -E: implicit import
|
||||
|
@ -24,7 +24,7 @@
|
||||
// CHECK-NEXT: note: diagnostic msg: {{.*}}.m
|
||||
// CHECK-NEXT: note: diagnostic msg: {{.*}}.cache
|
||||
|
||||
// CHECKSRC: @import cstd.stdio;
|
||||
// CHECKSRC: #pragma clang module import cstd.stdio
|
||||
|
||||
// CHECKSH: # Crash reproducer
|
||||
// CHECKSH-NEXT: # Driver args: "-fsyntax-only"
|
||||
@ -58,4 +58,4 @@
|
||||
// RUN: -fmodules-cache-path=%t/m/ 2>&1 \
|
||||
// RUN: | FileCheck %s --check-prefix=CHECKOVERLAY
|
||||
|
||||
// CHECKOVERLAY: @import cstd.stdio; /* clang -E: implicit import for "/{{[^ ].*}}/usr/include/stdio.h" */
|
||||
// CHECKOVERLAY: #pragma clang module import cstd.stdio /* clang -E: implicit import
|
||||
|
35
clang/test/Modules/import-syntax.c
Normal file
35
clang/test/Modules/import-syntax.c
Normal file
@ -0,0 +1,35 @@
|
||||
// RUN: rm -rf %t
|
||||
//
|
||||
// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fimplicit-module-maps -I%S/Inputs -verify -x c -DINCLUDE %s
|
||||
// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fimplicit-module-maps -I%S/Inputs -verify -x objective-c -DINCLUDE %s
|
||||
// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fimplicit-module-maps -I%S/Inputs -verify -x c++ -DINCLUDE %s
|
||||
//
|
||||
// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fimplicit-module-maps -I%S/Inputs -verify -x objective-c -DAT_IMPORT=1 %s
|
||||
// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fimplicit-module-maps -I%S/Inputs -verify -x objective-c++ -DAT_IMPORT=1 %s
|
||||
//
|
||||
// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fimplicit-module-maps -I%S/Inputs -verify -x c++ -fmodules-ts -DIMPORT=1 %s
|
||||
// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fimplicit-module-maps -I%S/Inputs -verify -x objective-c++ -fmodules-ts -DIMPORT=1 %s
|
||||
//
|
||||
// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fimplicit-module-maps -I%S/Inputs -verify -x c -DPRAGMA %s
|
||||
// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fimplicit-module-maps -I%S/Inputs -verify -x objective-c -DPRAGMA %s
|
||||
// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fimplicit-module-maps -I%S/Inputs -verify -x c++ -DPRAGMA %s
|
||||
|
||||
// expected-no-diagnostics
|
||||
|
||||
// All forms of module import should make both declarations and macros visible.
|
||||
|
||||
#if INCLUDE
|
||||
#include "dummy.h"
|
||||
#elif AT_IMPORT
|
||||
@import dummy;
|
||||
#elif IMPORT
|
||||
import dummy;
|
||||
#elif PRAGMA
|
||||
#pragma clang module import dummy
|
||||
#endif
|
||||
|
||||
#ifndef DUMMY_H
|
||||
#error "macros not visible"
|
||||
#endif
|
||||
|
||||
void *p = &dummy1;
|
@ -7,6 +7,6 @@
|
||||
// CHECK: # 1 "<module-includes>"
|
||||
// CHECK: # 1 "{{.*}}file.h" 1
|
||||
// CHECK: struct __FILE;
|
||||
// CHECK: #include "fwd.h" /* clang -E: implicit import for module fwd */
|
||||
// CHECK: #pragma clang module import fwd /* clang -E: implicit import for #include "fwd.h" */
|
||||
// CHECK: typedef struct __FILE FILE;
|
||||
// CHECK: # 2 "<module-includes>" 2
|
||||
|
@ -1,24 +1,30 @@
|
||||
// RUN: rm -rf %t
|
||||
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs -x c++ -E %s | \
|
||||
// RUN: FileCheck -strict-whitespace %s --check-prefix=CHECK --check-prefix=CXX --check-prefix=CXX-DASHE
|
||||
// RUN: FileCheck -strict-whitespace %s
|
||||
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs -x objective-c -E %s | \
|
||||
// RUN: FileCheck -strict-whitespace %s --check-prefix=CHECK --check-prefix=OBJC
|
||||
// RUN: FileCheck -strict-whitespace %s
|
||||
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs -x c++ -E -frewrite-includes %s | \
|
||||
// RUN: FileCheck -strict-whitespace %s --check-prefix=CHECK --check-prefix=CXX
|
||||
// RUN: FileCheck -strict-whitespace %s --check-prefix=REWRITE
|
||||
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs -x objective-c -E -frewrite-includes %s | \
|
||||
// RUN: FileCheck -strict-whitespace %s --check-prefix=CHECK --check-prefix=OBJC
|
||||
// RUN: FileCheck -strict-whitespace %s --check-prefix=REWRITE
|
||||
#include "dummy.h"
|
||||
#include "dummy.h"
|
||||
foo bar baz
|
||||
|
||||
// The weird {{ }} here is to prevent the -frewrite-includes test from matching its own CHECK lines.
|
||||
// EOF marker to ensure -frewrite-includes doesn't match its own CHECK lines.
|
||||
|
||||
// CXX: #include{{ }}"dummy.h"
|
||||
// CXX-DASHE-SAME: /* clang -E: implicit import for module dummy */
|
||||
// CXX: #include{{ }}"dummy.h"
|
||||
// CXX-DASHE-SAME: /* clang -E: implicit import for module dummy */
|
||||
// CXX: foo bar baz
|
||||
// REWRITE: #if 0
|
||||
// REWRITE: #include{{ }}"dummy.h"
|
||||
// REWRITE: #endif
|
||||
|
||||
// OBJC: @import{{ }}dummy; /* clang
|
||||
// OBJC: @import{{ }}dummy; /* clang
|
||||
// OBJC: foo bar baz
|
||||
// CHECK: #pragma clang module import dummy /* clang {{.*}} implicit import
|
||||
|
||||
// REWRITE: #if 0
|
||||
// REWRITE: #include{{ }}"dummy.h"
|
||||
// REWRITE: #endif
|
||||
|
||||
// CHECK: #pragma clang module import dummy /* clang {{.*}} implicit import
|
||||
|
||||
// CHECK: foo bar baz
|
||||
|
||||
// REWRITE: // {{EOF}} marker
|
||||
|
@ -16,11 +16,11 @@ void test() {
|
||||
|
||||
|
||||
// CHECK: int left_and_right(int *);{{$}}
|
||||
// CHECK-NEXT: @import diamond_left; /* clang -E: implicit import for "{{.*}}diamond_left.h" */{{$}}
|
||||
// CHECK-NEXT: #pragma clang module import diamond_left /* clang -E: implicit import for #import "diamond_left.h" */{{$}}
|
||||
|
||||
// CHECK: @import diamond_right; /* clang -E: implicit import for "{{.*}}diamond_right.h" */{{$}}
|
||||
// CHECK: @import diamond_right; /* clang -E: implicit import for "{{.*}}diamond_right.h" */{{$}}
|
||||
// CHECK: @import file; /* clang -E: implicit import for "{{.*}}file.h" */{{$}}
|
||||
// CHECK: #pragma clang module import diamond_right /* clang -E: implicit import for #import "diamond_right.h" */{{$}}
|
||||
// CHECK: #pragma clang module import diamond_right /* clang -E: implicit import for #import "diamond_right.h" */{{$}}
|
||||
// CHECK: #pragma clang module import file /* clang -E: implicit import for #include "file.h" */{{$}}
|
||||
// CHECK-NEXT: void test() {{{$}}
|
||||
// CHECK-NEXT: top_left_before();{{$}}
|
||||
// CHECK-NEXT: left_and_right();{{$}}
|
||||
|
@ -3,13 +3,13 @@
|
||||
|
||||
// CHECK: int bar();
|
||||
int bar();
|
||||
// CHECK: @import Module; /* clang -E: implicit import for "{{.*Headers[/\\]Module.h}}" */
|
||||
// CHECK: #pragma clang module import Module /* clang -E: implicit import for #include <Module/Module.h> */{{$}}
|
||||
#include <Module/Module.h>
|
||||
// CHECK: int foo();
|
||||
int foo();
|
||||
// CHECK: @import Module; /* clang -E: implicit import for "{{.*Headers[/\\]Module.h}}" */
|
||||
// CHECK: #pragma clang module import Module /* clang -E: implicit import for #include <Module/Module.h> */{{$}}
|
||||
#include <Module/Module.h>
|
||||
|
||||
#include "pp-modules.h" // CHECK: # 1 "{{.*}}pp-modules.h" 1
|
||||
// CHECK: @import Module; /* clang -E: implicit import for "{{.*}}Module.h" */{{$}}
|
||||
// CHECK: #pragma clang module import Module /* clang -E: implicit import for #include <Module/Module.h> */{{$}}
|
||||
// CHECK: # 14 "{{.*}}pp-modules.c" 2
|
||||
|
11
clang/test/Preprocessor/pragma_module.c
Normal file
11
clang/test/Preprocessor/pragma_module.c
Normal file
@ -0,0 +1,11 @@
|
||||
// RUN: %clang -cc1 -E -fmodules %s -verify
|
||||
|
||||
// Just checking the syntax here; the semantics are tested elsewhere.
|
||||
#pragma clang module import // expected-error {{expected identifier in module name}}
|
||||
#pragma clang module import ! // expected-error {{expected identifier in module name}}
|
||||
#pragma clang module import if // expected-error {{expected identifier in module name}}
|
||||
#pragma clang module import foo ? bar // expected-error {{expected '.' or end of directive after module name}}
|
||||
#pragma clang module import foo. // expected-error {{expected identifier}}
|
||||
#pragma clang module import foo.bar.baz.quux // expected-error {{module 'foo' not found}}
|
||||
|
||||
#error here // expected-error {{here}}
|
Loading…
x
Reference in New Issue
Block a user