[cfe-commits] r165821 - in /cfe/trunk: lib/Lex/ModuleMap.cpp test/Modules/Inputs/normal-module-map/nested_umbrella/1.h test/Modules/Inputs/normal-module-map/nested_umbrella/a-extras.h test/Modules/normal-module-map.cpp

Douglas Gregor dgregor at apple.com
Fri Oct 12 14:15:51 PDT 2012


Author: dgregor
Date: Fri Oct 12 16:15:50 2012
New Revision: 165821

URL: http://llvm.org/viewvc/llvm-project?rev=165821&view=rev
Log:
Sanitize the names of modules determined based on the names of headers
or directories, to make sure that they are identifiers that are not
keywords in any dialect. Fixes <rdar://problem/12489495>.

Added:
    cfe/trunk/test/Modules/Inputs/normal-module-map/nested_umbrella/1.h
    cfe/trunk/test/Modules/Inputs/normal-module-map/nested_umbrella/a-extras.h
Modified:
    cfe/trunk/lib/Lex/ModuleMap.cpp
    cfe/trunk/test/Modules/normal-module-map.cpp

Modified: cfe/trunk/lib/Lex/ModuleMap.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/ModuleMap.cpp?rev=165821&r1=165820&r2=165821&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/ModuleMap.cpp (original)
+++ cfe/trunk/lib/Lex/ModuleMap.cpp Fri Oct 12 16:15:50 2012
@@ -97,6 +97,54 @@
   this->Target = &Target;
 }
 
+/// \brief "Sanitize" a filename so that it can be used as an identifier.
+static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
+                                              SmallVectorImpl<char> &Buffer) {
+  if (Name.empty())
+    return Name;
+
+  // Check whether the filename is already an identifier; this is the common
+  // case.
+  bool isIdentifier = true;
+  for (unsigned I = 0, N = Name.size(); I != N; ++I) {
+    if (isalpha(Name[I]) || Name[I] == '_' || (isdigit(Name[I]) && I > 0))
+      continue;
+
+    isIdentifier = false;
+    break;
+  }
+
+  if (!isIdentifier) {
+    // If we don't already have something with the form of an identifier,
+    // create a buffer with the sanitized name.
+    Buffer.clear();
+    if (isdigit(Name[0]))
+      Buffer.push_back('_');
+    Buffer.reserve(Buffer.size() + Name.size());
+    for (unsigned I = 0, N = Name.size(); I != N; ++I) {
+      if (isalnum(Name[I]) || isspace(Name[I]))
+        Buffer.push_back(Name[I]);
+      else
+        Buffer.push_back('_');
+    }
+
+    Name = StringRef(Buffer.data(), Buffer.size());
+  }
+
+  while (llvm::StringSwitch<bool>(Name)
+#define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)
+#define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)
+#include "clang/Basic/TokenKinds.def"
+           .Default(false)) {
+    if (Name.data() != Buffer.data())
+      Buffer.append(Name.begin(), Name.end());
+    Buffer.push_back('_');
+    Name = StringRef(Buffer.data(), Buffer.size());
+  }
+
+  return Name;
+}
+
 Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
   llvm::DenseMap<const FileEntry *, Module *>::iterator Known
     = Headers.find(File);
@@ -135,7 +183,10 @@
         
         for (unsigned I = SkippedDirs.size(); I != 0; --I) {
           // Find or create the module that corresponds to this directory name.
-          StringRef Name = llvm::sys::path::stem(SkippedDirs[I-1]->getName());
+          SmallString<32> NameBuf;
+          StringRef Name = sanitizeFilenameAsIdentifier(
+                             llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
+                             NameBuf);
           Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
                                       Explicit).first;
           
@@ -149,7 +200,9 @@
         }
         
         // Infer a submodule with the same name as this header file.
-        StringRef Name = llvm::sys::path::stem(File->getName());
+        SmallString<32> NameBuf;
+        StringRef Name = sanitizeFilenameAsIdentifier(
+                           llvm::sys::path::stem(File->getName()), NameBuf);
         Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
                                     Explicit).first;
         Result->TopHeaders.insert(File);
@@ -218,7 +271,10 @@
       if (UmbrellaModule->InferSubmodules) {
         for (unsigned I = SkippedDirs.size(); I != 0; --I) {
           // Find or create the module that corresponds to this directory name.
-          StringRef Name = llvm::sys::path::stem(SkippedDirs[I-1]->getName());
+          SmallString<32> NameBuf;
+          StringRef Name = sanitizeFilenameAsIdentifier(
+                             llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
+                             NameBuf);
           Found = lookupModuleQualified(Name, Found);
           if (!Found)
             return false;
@@ -227,7 +283,10 @@
         }
         
         // Infer a submodule with the same name as this header file.
-        StringRef Name = llvm::sys::path::stem(Header->getName());
+        SmallString<32> NameBuf;
+        StringRef Name = sanitizeFilenameAsIdentifier(
+                           llvm::sys::path::stem(Header->getName()),
+                           NameBuf);
         Found = lookupModuleQualified(Name, Found);
         if (!Found)
           return false;
@@ -377,8 +436,10 @@
 #endif
 
       // FIXME: Do we want to warn about subframeworks without umbrella headers?
-      inferFrameworkModule(llvm::sys::path::stem(Dir->path()), SubframeworkDir,
-                           IsSystem, Result);
+      SmallString<32> NameBuf;
+      inferFrameworkModule(sanitizeFilenameAsIdentifier(
+                             llvm::sys::path::stem(Dir->path()), NameBuf),
+                           SubframeworkDir, IsSystem, Result);
     }
   }
 

Added: cfe/trunk/test/Modules/Inputs/normal-module-map/nested_umbrella/1.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/normal-module-map/nested_umbrella/1.h?rev=165821&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/normal-module-map/nested_umbrella/1.h (added)
+++ cfe/trunk/test/Modules/Inputs/normal-module-map/nested_umbrella/1.h Fri Oct 12 16:15:50 2012
@@ -0,0 +1 @@
+int one;

Added: cfe/trunk/test/Modules/Inputs/normal-module-map/nested_umbrella/a-extras.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/normal-module-map/nested_umbrella/a-extras.h?rev=165821&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/normal-module-map/nested_umbrella/a-extras.h (added)
+++ cfe/trunk/test/Modules/Inputs/normal-module-map/nested_umbrella/a-extras.h Fri Oct 12 16:15:50 2012
@@ -0,0 +1 @@
+int extra_a;

Modified: cfe/trunk/test/Modules/normal-module-map.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/normal-module-map.cpp?rev=165821&r1=165820&r2=165821&view=diff
==============================================================================
--- cfe/trunk/test/Modules/normal-module-map.cpp (original)
+++ cfe/trunk/test/Modules/normal-module-map.cpp Fri Oct 12 16:15:50 2012
@@ -33,3 +33,13 @@
 int testNestedUmbrellaB() {
   return nested_umbrella_b;
 }
+
+ at __experimental_modules_import nested_umbrella.a_extras;
+
+ at __experimental_modules_import nested_umbrella._1;
+
+ at __experimental_modules_import nested_umbrella.decltype_;
+
+int testSanitizedName() {
+  return extra_a + one + decltype_val;
+}





More information about the cfe-commits mailing list