Global inline assembler blocks are merged before parsing, so no specific
authorJoerg Sonnenberger <joerg@bec.de>
Mon, 16 Mar 2015 17:54:54 +0000 (17:54 +0000)
committerJoerg Sonnenberger <joerg@bec.de>
Mon, 16 Mar 2015 17:54:54 +0000 (17:54 +0000)
location data is available. If pragma handling wants to look up the
position, it finds the LLVM buffer and wants to compare it with the
special built-in buffer, failing badly. Extend to the special handling
of the built-in buffer to also check for the inline asm buffer. Expect
only a single asm buffer. Sort it between the built-in buffers and the
normal file buffers.

Fixes the assert part of PR 22576.

llvm-svn: 232389

clang/lib/Basic/SourceManager.cpp
clang/test/CodeGen/invalid_global_asm.c [new file with mode: 0644]

index 305dcd4..118e3f3 100644 (file)
@@ -2076,22 +2076,33 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
     return IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second);
   }
 
-  // This can happen if a location is in a built-ins buffer.
-  // But see PR5662.
+  // If we arrived here, the location is either in a built-ins buffer or
+  // associated with global inline asm. PR5662 and PR22576 are examples.
+
   // Clear the lookup cache, it depends on a common location.
   IsBeforeInTUCache.clear();
-  bool LIsBuiltins = strcmp("<built-in>",
-                            getBuffer(LOffs.first)->getBufferIdentifier()) == 0;
-  bool RIsBuiltins = strcmp("<built-in>",
-                            getBuffer(ROffs.first)->getBufferIdentifier()) == 0;
-  // built-in is before non-built-in
-  if (LIsBuiltins != RIsBuiltins)
-    return LIsBuiltins;
-  assert(LIsBuiltins && RIsBuiltins &&
-         "Non-built-in locations must be rooted in the main file");
-  // Both are in built-in buffers, but from different files. We just claim that
-  // lower IDs come first.
-  return LOffs.first < ROffs.first;
+  llvm::MemoryBuffer *LBuf = getBuffer(LOffs.first);
+  llvm::MemoryBuffer *RBuf = getBuffer(ROffs.first);
+  bool LIsBuiltins = strcmp("<built-in>", LBuf->getBufferIdentifier()) == 0;
+  bool RIsBuiltins = strcmp("<built-in>", RBuf->getBufferIdentifier()) == 0;
+  // Sort built-in before non-built-in.
+  if (LIsBuiltins || RIsBuiltins) {
+    if (LIsBuiltins != RIsBuiltins)
+      return LIsBuiltins;
+    // Both are in built-in buffers, but from different files. We just claim that
+    // lower IDs come first.
+    return LOffs.first < ROffs.first;
+  }
+  bool LIsAsm = strcmp("<inline asm>", LBuf->getBufferIdentifier()) == 0;
+  bool RIsAsm = strcmp("<inline asm>", RBuf->getBufferIdentifier()) == 0;
+  // Sort assembler after built-ins, but before the rest.
+  if (LIsAsm || RIsAsm) {
+    if (LIsAsm != RIsAsm)
+      return RIsAsm;
+    assert(LOffs.first == ROffs.first);
+    return false;
+  }
+  llvm_unreachable("Unsortable locations found");
 }
 
 void SourceManager::PrintStats() const {
diff --git a/clang/test/CodeGen/invalid_global_asm.c b/clang/test/CodeGen/invalid_global_asm.c
new file mode 100644 (file)
index 0000000..5b7e8b4
--- /dev/null
@@ -0,0 +1,5 @@
+// REQUIRES: arm-registered-target
+// RUN: not %clang_cc1 -emit-obj -triple armv6-unknown-unknown -o %t %s 2>&1 | FileCheck %s
+#pragma clang diagnostic ignored "-Wmissing-noreturn"
+__asm__(".Lfoo: movw r2, #:lower16:.Lbar - .Lfoo");
+// CHECK: <inline asm>:1:8: error: instruction requires: armv6t2