Global inline assembler blocks are merged before parsing, so no specific

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
This commit is contained in:
Joerg Sonnenberger 2015-03-16 17:54:54 +00:00
parent f2929c9b03
commit 1d3b431c98
2 changed files with 30 additions and 14 deletions

View 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 {

View File

@ -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