[cfe-commits] r151800 - in /cfe/trunk: include/clang/Basic/DiagnosticLexKinds.td include/clang/Lex/HeaderSearch.h include/clang/Lex/Preprocessor.h lib/Lex/PPDirectives.cpp lib/Lex/Pragma.cpp test/Preprocessor/pragma_microsoft.c
Aaron Ballman
aaron at aaronballman.com
Wed Feb 29 20:18:50 PST 2012
Author: aaronballman
Date: Wed Feb 29 22:18:49 2012
New Revision: 151800
URL: http://llvm.org/viewvc/llvm-project?rev=151800&view=rev
Log:
Implements support for #pragma include_alias in ms compatibility mode. Fixes PR10705.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
cfe/trunk/include/clang/Lex/HeaderSearch.h
cfe/trunk/include/clang/Lex/Preprocessor.h
cfe/trunk/lib/Lex/PPDirectives.cpp
cfe/trunk/lib/Lex/Pragma.cpp
cfe/trunk/test/Preprocessor/pragma_microsoft.c
Modified: cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td?rev=151800&r1=151799&r2=151800&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td Wed Feb 29 22:18:49 2012
@@ -292,6 +292,15 @@
ExtWarn<"__has_warning expected option name (e.g. \"-Wundef\")">,
InGroup<MalformedWarningCheck>;
+def warn_pragma_include_alias_mismatch :
+ ExtWarn<"pragma include_alias requires matching include directives "
+ "(e.g include_alias(\"foo.h\", \"bar.h\") or "
+ "include_alias(<foo.h>, <bar.h>))">,
+ InGroup<UnknownPragmas>;
+def warn_pragma_include_alias_expected :
+ ExtWarn<"pragma include_alias expected '%0'">,
+ InGroup<UnknownPragmas>;
+
def err__Pragma_malformed : Error<
"_Pragma takes a parenthesized string literal">;
def err_pragma_comment_malformed : Error<
Modified: cfe/trunk/include/clang/Lex/HeaderSearch.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/HeaderSearch.h?rev=151800&r1=151799&r2=151800&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/HeaderSearch.h (original)
+++ cfe/trunk/include/clang/Lex/HeaderSearch.h Wed Feb 29 22:18:49 2012
@@ -154,6 +154,9 @@
llvm::StringMap<const DirectoryEntry *, llvm::BumpPtrAllocator>
FrameworkMap;
+ llvm::StringMap<std::pair<StringRef, bool>, llvm::BumpPtrAllocator>
+ IncludeAliasMap;
+
/// HeaderMaps - This is a mapping from FileEntry -> HeaderMap, uniquing
/// headermaps. This vector owns the headermap.
std::vector<std::pair<const FileEntry*, const HeaderMap*> > HeaderMaps;
@@ -217,6 +220,25 @@
SystemDirIdx++;
}
+ /// AddHeaderMapping -- Map the source include name to the dest include name
+ void AddHeaderMapping(const StringRef& Source, const StringRef& Dest,
+ bool IsAngled) {
+ IncludeAliasMap[Source] = std::make_pair(Dest, IsAngled);
+ }
+
+ StringRef MapHeader(const StringRef& Source, bool isAngled) {
+ // Do any filename replacements before anything else
+ llvm::StringMap<std::pair<StringRef,bool>>::const_iterator iter =
+ IncludeAliasMap.find(Source);
+ if (iter != IncludeAliasMap.end()) {
+ // If the angling matches, then we've found a replacement
+ if (iter->second.second == isAngled) {
+ return iter->second.first;
+ }
+ }
+ return Source;
+ }
+
/// \brief Set the path to the module cache.
void setModuleCachePath(StringRef CachePath) {
ModuleCachePath = CachePath;
Modified: cfe/trunk/include/clang/Lex/Preprocessor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/Preprocessor.h?rev=151800&r1=151799&r2=151800&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/Preprocessor.h (original)
+++ cfe/trunk/include/clang/Lex/Preprocessor.h Wed Feb 29 22:18:49 2012
@@ -1262,6 +1262,7 @@
void HandlePragmaMessage(Token &MessageTok);
void HandlePragmaPushMacro(Token &Tok);
void HandlePragmaPopMacro(Token &Tok);
+ void HandlePragmaIncludeAlias(Token &Tok);
IdentifierInfo *ParsePragmaPushOrPopMacro(Token &Tok);
// Return true and store the first token only if any CommentHandler
Modified: cfe/trunk/lib/Lex/PPDirectives.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPDirectives.cpp?rev=151800&r1=151799&r2=151800&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/PPDirectives.cpp (original)
+++ cfe/trunk/lib/Lex/PPDirectives.cpp Wed Feb 29 22:18:49 2012
@@ -1304,6 +1304,9 @@
PragmaARCCFCodeAuditedLoc = SourceLocation();
}
+ // Map the filename
+ Filename = HeaderInfo.MapHeader(Filename, isAngled);
+
// Search include directories.
const DirectoryLookup *CurDir;
SmallString<1024> SearchPath;
Modified: cfe/trunk/lib/Lex/Pragma.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/Pragma.cpp?rev=151800&r1=151799&r2=151800&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/Pragma.cpp (original)
+++ cfe/trunk/lib/Lex/Pragma.cpp Wed Feb 29 22:18:49 2012
@@ -663,6 +663,101 @@
}
}
+void Preprocessor::HandlePragmaIncludeAlias(Token& Tok) {
+ // We will either get a quoted filename or a bracketed filename, and we
+ // have to track which we got. The first filename is the source name,
+ // and the second name is the mapped filename. If the first is quoted,
+ // the second must be as well (cannot mix and match quotes and brackets).
+ SourceLocation Loc = Tok.getLocation();
+
+ // Get the open paren
+ Lex(Tok);
+ if (Tok.isNot(tok::l_paren)) {
+ Diag(Tok, diag::warn_pragma_include_alias_expected) << "(";
+ return;
+ }
+
+ // We expect either a quoted string literal, or a bracketed name
+ Token SourceFilenameTok;
+ CurPPLexer->LexIncludeFilename(SourceFilenameTok);
+ if (SourceFilenameTok.is(tok::eod)) {
+ // The diagnostic has already been handled
+ return;
+ }
+
+ StringRef SourceFileName;
+ SmallString<128> FileNameBuffer;
+ if (SourceFilenameTok.is(tok::string_literal) ||
+ SourceFilenameTok.is(tok::angle_string_literal)) {
+ SourceFileName = getSpelling(SourceFilenameTok, FileNameBuffer);
+ } else if (SourceFilenameTok.is(tok::less)) {
+ // This could be a path instead of just a name
+ FileNameBuffer.push_back('<');
+ SourceLocation End;
+ if (ConcatenateIncludeName(FileNameBuffer, End))
+ return; // Diagnostic already emitted
+ SourceFileName = FileNameBuffer.str();
+ } else {
+ Diag(Tok, diag::warn_pragma_include_alias_expected) << "include filename";
+ return;
+ }
+ FileNameBuffer.clear();
+
+ // Now we expect a comma, followed by another include name
+ Lex(Tok);
+ if (Tok.isNot(tok::comma)) {
+ Diag(Tok, diag::warn_pragma_include_alias_expected) << ",";
+ return;
+ }
+
+ Token ReplaceFilenameTok;
+ CurPPLexer->LexIncludeFilename(ReplaceFilenameTok);
+ if (ReplaceFilenameTok.is(tok::eod)) {
+ // The diagnostic has already been handled
+ return;
+ }
+
+ StringRef ReplaceFileName;
+ if (ReplaceFilenameTok.is(tok::string_literal) ||
+ ReplaceFilenameTok.is(tok::angle_string_literal)) {
+ ReplaceFileName = getSpelling(ReplaceFilenameTok, FileNameBuffer);
+ } else if (ReplaceFilenameTok.is(tok::less)) {
+ // This could be a path instead of just a name
+ FileNameBuffer.push_back('<');
+ SourceLocation End;
+ if (ConcatenateIncludeName(FileNameBuffer, End))
+ return; // Diagnostic already emitted
+ ReplaceFileName = FileNameBuffer.str();
+ } else {
+ Diag(Tok, diag::warn_pragma_include_alias_expected) << "include filename";
+ return;
+ }
+
+ // Finally, we expect the closing paren
+ Lex(Tok);
+ if (Tok.isNot(tok::r_paren)) {
+ Diag(Tok, diag::warn_pragma_include_alias_expected) << ")";
+ return;
+ }
+
+ // Now that we have the source and target filenames, we need to make sure
+ // they're both of the same type (angled vs non-angled)
+ bool SourceIsAngled =
+ GetIncludeFilenameSpelling(SourceFilenameTok.getLocation(),
+ SourceFileName);
+ bool ReplaceIsAngled =
+ GetIncludeFilenameSpelling(ReplaceFilenameTok.getLocation(),
+ ReplaceFileName);
+ if (SourceIsAngled != ReplaceIsAngled) {
+ Diag(Loc, diag::warn_pragma_include_alias_mismatch);
+ return;
+ }
+
+ // Now we can let the include handler know about this mapping
+ getHeaderSearchInfo().AddHeaderMapping(SourceFileName, ReplaceFileName,
+ SourceIsAngled);
+}
+
/// AddPragmaHandler - Add the specified pragma handler to the preprocessor.
/// If 'Namespace' is non-null, then it is a token required to exist on the
/// pragma line before the pragma string starts, e.g. "STDC" or "GCC".
@@ -943,6 +1038,15 @@
}
};
+/// PragmaIncludeAliasHandler - "#pragma include_alias("...")".
+struct PragmaIncludeAliasHandler : public PragmaHandler {
+ PragmaIncludeAliasHandler() : PragmaHandler("include_alias") {}
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &IncludeAliasTok) {
+ PP.HandlePragmaIncludeAlias(IncludeAliasTok);
+ }
+};
+
/// PragmaMessageHandler - "#pragma message("...")".
struct PragmaMessageHandler : public PragmaHandler {
PragmaMessageHandler() : PragmaHandler("message") {}
@@ -1095,5 +1199,6 @@
// MS extensions.
if (Features.MicrosoftExt) {
AddPragmaHandler(new PragmaCommentHandler());
+ AddPragmaHandler(new PragmaIncludeAliasHandler());
}
}
Modified: cfe/trunk/test/Preprocessor/pragma_microsoft.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Preprocessor/pragma_microsoft.c?rev=151800&r1=151799&r2=151800&view=diff
==============================================================================
--- cfe/trunk/test/Preprocessor/pragma_microsoft.c (original)
+++ cfe/trunk/test/Preprocessor/pragma_microsoft.c Wed Feb 29 22:18:49 2012
@@ -38,3 +38,20 @@
// this warning should go away.
MACRO_WITH__PRAGMA // expected-warning {{expression result unused}}
}
+
+
+// This should include macro_arg_directive even though the include
+// is looking for test.h This allows us to assign to "n"
+#pragma include_alias("test.h", "macro_arg_directive.h" )
+#include "test.h"
+void test( void ) {
+ n = 12;
+}
+
+#pragma include_alias("foo.h", <bar.h>) // expected-warning {{pragma include_alias requires matching include directives (e.g include_alias("foo.h", "bar.h") or include_alias(<foo.h>, <bar.h>))}}
+#pragma include_alias("test.h") // expected-warning {{pragma include_alias expected ','}}
+
+// Make sure that the names match exactly for a replacement, including path information. If
+// this were to fail, we would get a file not found error
+#pragma include_alias(".\pp-record.h", "does_not_exist.h")
+#include "pp-record.h"
More information about the cfe-commits
mailing list